Index: /trunk/src/emx/ChangeLog.LIBC
===================================================================
--- /trunk/src/emx/ChangeLog.LIBC	(revision 2000)
+++ /trunk/src/emx/ChangeLog.LIBC	(revision 2001)
@@ -8,12 +8,15 @@
         o Default TCPIP mode is __USB_LIBC_TCPIP. When either TCPV40HDRS or TCPV41HDRS
           are defined we are in strict mode and __USB_LIBC_TCPIP will not be defined.
-
     - libomflib, emxomfar:
         o Allow multiple modules by the same basename. This is not in tradition with
           other librarians, but it solves incompatible behaviour between emxomfar and ar.
-
     - ld:
         o Avoid using alloca since we might easily run out of stack for big objects
           with debuginfo.
+    - emxomf:
+        o Added support for new EMX a.out stab N_EXP (0x6c). This encodes export
+          definitions. (gcc can do __declspec(dllexport) now.)
+          TODO: ld needs updating, probably this is the right time to drop the
+                old ld and fixup the binutils port!
 
 2005-05-08: knut st. osmundsen <bird-gccos2-spam@anduin.net>
Index: /trunk/src/emx/include/a_out.h
===================================================================
--- /trunk/src/emx/include/a_out.h	(revision 2000)
+++ /trunk/src/emx/include/a_out.h	(revision 2001)
@@ -141,6 +141,7 @@
 #define N_WEAKB 0x11		/* Weak bss symbol.  */
 /* emx */
-#define N_IMP1  0x68            /* Import definition symbol */
+#define N_IMP1  0x68            /* Import reference symbol */
 #define N_IMP2  0x6a		/* Import definition symbol */
+#define N_EXP   0x6c		/* Export definition symbol */
 
 
Index: /trunk/src/emx/include/sys/omflib.h
===================================================================
--- /trunk/src/emx/include/sys/omflib.h	(revision 2000)
+++ /trunk/src/emx/include/sys/omflib.h	(revision 2001)
@@ -78,7 +78,7 @@
 
 #if !defined (IMPDEF_CLASS)
-#define IMPDEF_CLASS    0xa0
+#define IMPDEF_CLASS    CLASS_OMFEXT
 #define LIBMOD_CLASS    0xa3
-#define IMPDEF_SUBTYPE  0x01
+#define IMPDEF_SUBTYPE  OMFEXT_IMPDEF
 #endif
 
Index: /trunk/src/emx/src/emxomf/emxomf.c
===================================================================
--- /trunk/src/emx/src/emxomf/emxomf.c	(revision 2000)
+++ /trunk/src/emx/src/emxomf/emxomf.c	(revision 2001)
@@ -575,6 +575,6 @@
     {
       int sym_ofs = i;
-      s = name;
-      if (strip_underscore (str_ptr + i))
+      s = (const byte *)name;
+      if (strip_underscore ((const char *)(str_ptr + i)))
         ++i;
       if (memcmp (name, str_ptr+i, len+1) == 0)
@@ -594,5 +594,5 @@
 	      }
 	}
-      i += strlen (str_ptr+i) + 1;
+      i += strlen ((const char *)(str_ptr + i)) + 1;
     }
   return NULL;                  /* Symbol not found */
@@ -917,5 +917,5 @@
 
 
-/* Put the null-terminated string pszName into the current OMF record.
+/* Put the string pszName 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
@@ -924,7 +924,6 @@
    message and abort. */
 
-static void put_str(const char *pszName)
-{
-    int cch = strlen(pszName);
+static void put_nstr(const char *pszName, size_t cch)
+{
     if (cch > 255)
     {
@@ -937,5 +936,5 @@
         const char *psz;
         unsigned    uHash;
-        for (psz = pszName, uHash = 5381; *psz; psz++)   /* hash alg: original djb2. */
+        for (psz = pszName, uHash = 5381, cch2 = cch; cch > 0; psz++, cch--) /* hash alg: original djb2. */
             uHash += (uHash << 5) + *psz;
         cch2 = sprintf(szHash, "!_%X", 0x7fffffff & uHash);
@@ -958,4 +957,13 @@
         out_idx += cch;
     }
+}
+
+/* Put the null-terminated string pszName into the current OMF record.
+   See put_nstr() for full details on string handling. */
+
+static void put_str(const char *pszName)
+{
+    int cch = strlen(pszName);
+    put_nstr(pszName, cch);
 }
 
@@ -1059,5 +1067,5 @@
    and quit. */
 
-static void put_mem (const char *src, int size)
+static void put_mem (const void *src, int size)
 {
   if (!fits (size))
@@ -1147,5 +1155,5 @@
     else if (sym_ptr[i].n_type == N_EXT && sym_ptr[i].n_value == 0)
       {
-        name = str_ptr + sym_ptr[i].n_un.n_strx;
+        name = (const char *)(str_ptr + sym_ptr[i].n_un.n_strx);
         sym_more[i].index = sym_index++;
         if (memcmp (name, "_16_", 4) == 0)
@@ -1161,5 +1169,5 @@
           }
         sym_more[i].index = sym_index++;
-        add_extdef (&started, str_ptr + sym_ptr[i].n_un.n_strx, sym_more[i].hll_type);
+        add_extdef (&started, (const char *)(str_ptr + sym_ptr[i].n_un.n_strx), sym_more[i].hll_type);
       }
 #if 1 /* this isn't actually required if only the assembler could do what it's supposed to... */
@@ -1168,5 +1176,5 @@
            external records for this, perhaps...
            At least I can't see why this will be wrong. */
-        name = str_ptr + sym_ptr[i].n_un.n_strx;
+        name = (const char *)(str_ptr + sym_ptr[i].n_un.n_strx);
         sym_more[i].index = sym_index++;
         add_extdef (&started, name, sym_more[i].hll_type);
@@ -1227,5 +1235,5 @@
     if ((sym_ptr[i].n_type >= N_WEAKA) && (sym_ptr[i].n_type <= N_WEAKB))
       {
-        const char *name = str_ptr + sym_ptr[i].n_un.n_strx;
+        const char *name = (const char *)(str_ptr + sym_ptr[i].n_un.n_strx);
 
         int public = N_EXT;
@@ -1401,11 +1409,11 @@
       {
         init_rec (ALIAS);
-        put_sym (str_ptr + sym_ptr[i].n_un.n_strx);
-        put_sym (str_ptr + sym_ptr[i+1].n_un.n_strx);
+        put_sym ((const char *)(str_ptr + sym_ptr[i].n_un.n_strx));
+        put_sym ((const char *)(str_ptr + sym_ptr[i+1].n_un.n_strx));
         write_rec ();
 
         if (out_lib != NULL)
           {
-            pub_name = str_ptr + sym_ptr[i].n_un.n_strx;
+            pub_name = (const char *)(str_ptr + sym_ptr[i].n_un.n_strx);
             if (strip_underscore (pub_name))
               ++pub_name;
@@ -1454,5 +1462,5 @@
         if ((address >= 0x10000 || force_big) == big)
           {
-            name = str_ptr + sym_ptr[i].n_un.n_strx;
+            name = (const char *)(str_ptr + sym_ptr[i].n_un.n_strx);
             if (   (sym_ptr[i].n_type & N_EXT)
                 || (type == N_TEXT && strncmp (name, "___POST$", 8) == 0)
@@ -1518,5 +1526,5 @@
       if ((sym_ptr[i].n_type & ~N_EXT) == N_TEXT)
         {
-          const char * name    = str_ptr + sym_ptr[i].n_un.n_strx;
+          const char * name    = (const char *)(str_ptr + sym_ptr[i].n_un.n_strx);
           dword        address = sym_ptr[i].n_value;
           if (   (sym_ptr[i].n_type & N_EXT)
@@ -1610,5 +1618,5 @@
     else if (sym_ptr[i].n_type == N_EXT && sym_ptr[i].n_value != 0)
       {
-        name = str_ptr + sym_ptr[i].n_un.n_strx;
+        name = (const char *)(str_ptr + sym_ptr[i].n_un.n_strx);
         sym_more[i].index = sym_index++;
         if (memcmp (name, "_16_", 4) == 0)
@@ -1628,4 +1636,6 @@
         put_idx (0);                  /* Type index */
         put_8 (0x62);                 /* Data type */
+        if (size < 4)
+            size = 4; /* VAC308 ilink freaks out if size = 1 or something */
         if (size < 0x80)
           put_8 (size);
@@ -2224,5 +2234,5 @@
              this set is already known. */
 
-          name = str_ptr + sym_ptr[i].n_un.n_strx;
+          name = (const char *)(str_ptr + sym_ptr[i].n_un.n_strx);
           for (set_ptr = sets; set_ptr != NULL; set_ptr = set_ptr->next)
             if (strcmp (set_ptr->name, name) == 0)
@@ -2475,5 +2485,5 @@
          get the string from the cache. */
 
-      sym_name = str_ptr + sym_ptr[rel->r_symbolnum].n_un.n_strx;
+      sym_name = (const char *)(str_ptr + sym_ptr[rel->r_symbolnum].n_un.n_strx);
       for (p = modstr_cache; p != NULL; p = p->next)
         if (strcmp (p->symbol, sym_name) == 0)
@@ -2528,5 +2538,5 @@
                   case N_TEXT|N_EXT:
                   case N_DATA|N_EXT:
-                    if (strcmp (m_str + m_sym[i].n_un.n_strx, sym_name) == 0)
+                    if (strcmp ((const char *)(m_str + m_sym[i].n_un.n_strx), sym_name) == 0)
                       {
                         m_sym += i; found = TRUE; break;
@@ -2661,8 +2671,8 @@
       {
       case N_IMP1|N_EXT:
-        name1 = str_ptr + sym_ptr[i].n_un.n_strx;
+        name1 = (const char *)(str_ptr + sym_ptr[i].n_un.n_strx);
         break;
       case N_IMP2|N_EXT:
-        name2 = str_ptr + sym_ptr[i].n_un.n_strx;
+        name2 = (const char *)(str_ptr + sym_ptr[i].n_un.n_strx);
         break;
       default:
@@ -2732,8 +2742,8 @@
         {
         case N_IMP1|N_EXT:
-          name1 = str_ptr + sym_ptr[i].n_un.n_strx;
+          name1 = (const char *)(str_ptr + sym_ptr[i].n_un.n_strx);
           break;
         case N_IMP2|N_EXT:
-          name2 = str_ptr + sym_ptr[i].n_un.n_strx;
+          name2 = (const char *)(str_ptr + sym_ptr[i].n_un.n_strx);
           break;
         }
@@ -2829,5 +2839,5 @@
       case N_TEXT|N_EXT:
         if (pub_name != NULL) return FALSE;
-        pub_name = str_ptr + sym_ptr[i].n_un.n_strx;
+        pub_name = (const char *)(str_ptr + sym_ptr[i].n_un.n_strx);
         break;
 
@@ -2837,5 +2847,5 @@
 
       case N_SETT|N_EXT:
-        if (strcmp (str_ptr + sym_ptr[i].n_un.n_strx, "__os2dll") != 0)
+        if (strcmp ((const char *)(str_ptr + sym_ptr[i].n_un.n_strx), "__os2dll") != 0)
           return FALSE;
         table_off = sym_ptr[i].n_value;
@@ -2889,4 +2899,111 @@
   make_import (pub_name, ord != 0 ? NULL : proc_name, ord, dll_name);
   return TRUE;
+}
+
+/**
+ * Emits a OMF export record if the symbols is defined in this module.
+ */
+static void make_export(const char *pszSymbol, size_t cchSymbol,
+                        const char *pszExpName, size_t cchExpName, unsigned iOrdinal)
+{
+    const struct nlist *pSym;
+    char *pszSym = alloca(cchSymbol + 1);
+    memcpy(pszSym, pszSymbol, cchSymbol);
+    pszSym[cchSymbol] = '\0';
+
+    pSym = find_symbol(pszSym);
+    if (pSym)
+    {
+        /*
+         * Write the export definition record.
+         */
+        uint8_t fFlags = 0;
+        if (iOrdinal)
+            fFlags |= 1 << 7; /* have ordinal */
+        if (cchExpName && !iOrdinal)
+           fFlags |= 1 << 6; /* resident name */
+
+        init_rec(COMENT);
+        put_8(0x00);
+        put_8(CLASS_OMFEXT);
+        put_8(OMFEXT_EXPDEF);
+        put_8(fFlags);
+        put_nstr(pszExpName, cchExpName);
+        put_nstr(pszSymbol, cchSymbol);
+        if (iOrdinal)
+            put_16(iOrdinal);
+        write_rec();
+    }
+}
+
+
+/* Convert export entries.
+
+   The exports are encoded as N_EXT (0x6c) stab entries. The value is -42,
+   and the symbol name is on the form: "<exportname>,<ordinal>=<symbol>,code|data"
+   The exportname can be empty if ordinal is not 0. Ordinal 0 means not exported by
+   any special ordinal number.
+
+   Export entries for symbols which are not defined in the object are ignored. */
+static void write_export (void)
+{
+    int i;
+
+    /* Search the symbol table for N_IMP1 and N_IMP2 symbols.  These are
+       unique to import modules. */
+
+    for (i = 0; i < sym_count; ++i)
+    {
+        const char *pszName;
+        size_t      cchName;
+        const char *pszOrdinal;
+        const char *pszSymbol;
+        size_t      cchSymbol;
+        const char *pszType;
+        int         iOrdinal;
+        char       *pszOrdinalEnd;
+        if (sym_ptr[i].n_type != N_EXP)
+            continue;
+        pszName = (const char *)(str_ptr + sym_ptr[i].n_un.n_strx);
+
+        /*
+         * Parse it.
+         */
+        /* find equal sign first, we'll use this for validating the ordinal. */
+        pszSymbol = strchr(pszName, '=');
+        if (!pszSymbol)
+            error("Invalid export record: missing `='. \nstabs: %s", pszName);
+
+        /* ordinal */
+        pszOrdinal = strchr(pszName, ',');
+        if (!pszOrdinal || pszOrdinal >= pszSymbol)
+            error("Invalid export record: missing ordinal.\nstabs: %s", pszName);
+        cchName = pszOrdinal - pszName;
+        pszOrdinal++;
+        iOrdinal = strtol(pszOrdinal, &pszOrdinalEnd, 0);
+        if (iOrdinal < 0 || iOrdinal >= 0x10000)
+            error("Invalid export record: ordinal value is out of range (0-65k): %d\nstabs:%s",
+                  iOrdinal, pszName);
+        if (pszOrdinalEnd != pszSymbol)
+            error("Invalid export record: ordinal field doesn't end at `=.\nstabs:%s", pszName);
+
+        /* type and symbol */
+        pszSymbol++;
+        pszType = strchr(pszSymbol, ',');
+        if (!pszType)
+            error("Invalid export record: Symbol type is missing\nstabs:%s", pszName);
+        cchSymbol = pszType - pszSymbol;
+        pszType++;
+        if (strcmp(pszType, "code") && strcmp(pszType, "data") && strcmp(pszType, "bss") && strcmp(pszType, "common"))
+            error("Invalid export record: Invalid symbol type: %s\nstabs:%s", pszType, pszName);
+        if (!cchSymbol)
+            error("Invalid export record: No (internal) symbol name.\nstabs:%s", pszName);
+
+        /*
+         * Hand it on to the worker which looks up the symbol
+         * and emits the OMF export record if found.
+         */
+        make_export(pszSymbol, cchSymbol, pszName, cchName, iOrdinal);
+    }
 }
 
@@ -2951,5 +3068,5 @@
     if (sym_ptr[i].n_type == N_SO)
       {
-        p1 = str_ptr + sym_ptr[i].n_un.n_strx;
+        p1 = (const char *)(str_ptr + sym_ptr[i].n_un.n_strx);
         len = strlen (p1);
         if (len > 0 && p1[len-1] == '/' )
@@ -3234,5 +3351,5 @@
       {
       case N_SOL:
-        file_index = file_find (str_ptr + sym_ptr[i].n_un.n_strx);
+        file_index = file_find ((const char *)(str_ptr + sym_ptr[i].n_un.n_strx));
         break;
       case N_SLINE:
@@ -3490,4 +3607,5 @@
                     case N_IMP1|N_EXT:
                     case N_IMP2|N_EXT:
+      case N_EXP:   case N_EXP|N_EXT:
       case N_LSYM:
       case N_SOL:
@@ -3707,4 +3825,9 @@
   weak_process ();
 
+  /* Convert imports and exports. These show up very early in VAC
+     generated OMF files. */
+  write_import_i2 ();
+  write_export ();
+
   /* Define external, communal and public symbols (EXTDEF, WKEXT,
      COMDEF, PUBDEF, and ALIAS records).  This must be done after
@@ -3717,5 +3840,4 @@
   write_set_pub ();
   write_alias ();
-  write_import_i2 ();
 
   /* Write link pass separator. */
Index: /trunk/src/emx/src/emxomf/weakld.c
===================================================================
--- /trunk/src/emx/src/emxomf/weakld.c	(revision 2000)
+++ /trunk/src/emx/src/emxomf/weakld.c	(revision 2001)
@@ -349,5 +349,7 @@
         /** @} */
         /** no idea what this implies */
-        WLDSEF_NODATA           = 0x04
+        WLDSEF_NODATA           = 0x04,
+        /** From an EXPORT section of a .DEF-file. */
+        WLDSEF_DEF_FILE         = 0x80
     }                   fExport;
     /** Export word count. */
@@ -2075,6 +2077,10 @@
     if (pSym->fFlags & WLDSF_EXPORT)
     {
-        /* Just warn and ignore */
-        modWarn(pMod, "Export '%s' is already defined.", pSym->pszName);
+        if (    (pSym->fExport & WLDSEF_DEF_FILE)
+            &&  (fExport & WLDSEF_DEF_FILE))
+            modWarn(pMod, "Export '%s' is already defined.", pSym->pszName);
+        if (    !(pSym->fExport & WLDSEF_DEF_FILE)
+            &&  (fExport & WLDSEF_DEF_FILE))
+            pSym->fExport = fExport;
     }
     else
@@ -2518,10 +2524,10 @@
                                 ul = 0;                         /* ordinal */
                                 if (*u1.pch & 0x80)
-                                    ul = OMF_BYTE();
+                                    ul = OMF_WORD();
                                 pSym = symAddExport(pWld, pMod, fLibSearch,
                                                     (*u1.puch & 0x40 ? WLDSEF_RESIDENT : WLDSEF_DEFAULT) | (*u1.puch & 0x20 ? WLDSEF_NODATA : 0),
                                                     ((unsigned)*u1.puch) & 0x1f,
-                                                    u2.pch + 1, *u1.puch,
-                                                    u3.pch + 1, *u2.puch,
+                                                    u2.pch + 1, *u2.puch,
+                                                    u3.pch + 1, *u3.puch,
                                                     ul);
                                 if (!pSym) goto failure;
@@ -2941,5 +2947,5 @@
                 cWords = pStmt->export.pwords;
             pSym = symAddExport(pParam->pWld, pParam->pMod, 0,
-                                fFlags, cWords,
+                                fFlags | WLDSEF_DEF_FILE, cWords,
                                 pStmt->export.entryname, -1,
                                 pStmt->export.internalname, -1,
