Index: trunk/src/emx/src/emxomf/weakld.c
===================================================================
--- trunk/src/emx/src/emxomf/weakld.c	(revision 489)
+++ trunk/src/emx/src/emxomf/weakld.c	(revision 491)
@@ -25,5 +25,5 @@
 
 /** @page weakld        Weak Pre-Linker
- * 
+ *
  * In order to get the weak symbols somewhat right it looks like we have to do
  * the pass1 of the linking process in order to resolve the weak symbols.
@@ -33,5 +33,5 @@
  * @subsection          Symbols
  *
- * There is a couple of symbol types, but we can skip most of them for this 
+ * There is a couple of symbol types, but we can skip most of them for this
  * pre-linking operation. We use one symbol type which is public or global
  * symbols if you like. Perhaps it would be wise to devide them into separat
@@ -48,4 +48,20 @@
 #define OMF_MAX_REC         1024
 
+/** helper to make verbose only output. */
+#define WLDINFO(pWld, a)    do { if (pWld->fFlags & WLDC_VERBOSE) wldInfo a; } while (0)
+
+/** Internal error */
+#define WLDINTERR(pWld, pMod)   wldIntErr(pWld, pMod, __FILE__, __LINE__, __FUNCTION__);
+
+
+/** Helpers for checking if a symbol is defined strongly. */
+#define SYM_IS_DEFINED(fFlags)   (   (fFlags & (WLDSF_TYPEMASK | WLDSF_WEAK)) == WLDSF_PUBLIC \
+                                  || (fFlags & (WLDSF_TYPEMASK | WLDSF_WEAK)) == WLDSF_COMM \
+                                  || (fFlags & (WLDSF_TYPEMASK | WLDSF_WEAK)) == WLDSF_IMPORT \
+                                  )
+/** Helpers for checking if a symbol is strongly undefined. No weaks included! */
+#define SYM_IS_UNDEFINED(fFlags) (   (fFlags & (WLDSF_TYPEMASK | WLDSF_WEAK)) == WLDSF_UNDEF)
+
+
 
 /*******************************************************************************
@@ -53,6 +69,7 @@
 *******************************************************************************/
 #include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
 #include <string.h>
-#include <stdlib.h>
 #include <sys/types.h>
 #include <sys/omflib.h>
@@ -61,10 +78,10 @@
 #include "weakld.h"
 
- 
+
 /*******************************************************************************
 *   Structures and Typedefs                                                    *
 *******************************************************************************/
 /**
- * Library structure 
+ * Library structure
  */
 typedef struct wldlib
@@ -77,9 +94,9 @@
     struct wldlib * pNext;
 } WLDLIB, *PWLDLIB;
- 
-
-/**
- * Module structure 
- */    
+
+
+/**
+ * Module structure
+ */
 typedef struct wldmod
 {
@@ -95,5 +112,5 @@
     struct wldmod *pNext;
 } WLDMOD, *PWLDMOD;
- 
+
 
 /**
@@ -107,25 +124,25 @@
     const char *        pszWeakName;
 
-    /** Symbol type. */
-    enum {
-        WLDST_PUBLIC
-        }               eType;
-
     /** Symbol flags. */
     enum {
-        /** @group Symbol state 
+        /** @group Symbol Type
          * @{ */
-        /* Mask of the symbol state. */
-        WLDSF_STATEMASK = 0x000f,
+        /* Mask of the symbol type. */
+        WLDSF_TYPEMASK  = 0x000f,
         /** Strong symbol.
          * A strong definition exists for this symbol (PUBDEF). */
-        WLDSF_STRONG    = 0x0001,
-        /** Communal data/code. 
+        WLDSF_PUBLIC    = 0x0001,
+        /** Communal data/code.
          * Communal definition exists for this symbol.
          * If a PUBDEF is found for this symbol it will become strong. */
         WLDSF_COMM      = 0x0002,
+        /** Imported symbol.
+         * This symbol is imported.
+         * Note that when combined with WLDSF_LIBSEARCH a symbol in this type
+         * will yield to stronger definitions with a little warning. */
+        WLDSF_IMPORT    = 0x0003,
         /** Undefined symbol.
          * This symbol is not yet defined anywhere. */
-        WLDSF_UNDEF     = 0x0003,
+        WLDSF_UNDEF     = 0x0004,
         /** Weak external.
          * This symbol doesn't need to be resolved as it have a default
@@ -134,68 +151,91 @@
          * WLDSF_UNDEF.
          */
-        WLDSF_WKEXT     = 0x0004,
+        WLDSF_WKEXT     = 0x0005,
         /** @} */
 
-        /** Weak symbol. 
-         * This symbol doesn't need to be resolved (if WLDSF_UNDEF), or 
+        /** Uncertain undefined symbol.
+         * We're still processing the module containing this and the uncertainty
+         * we're facing is that a WLDSF_UNDEF may changed to an WLDSF_WKEXT
+         * upon encountering a WKEXT COMENT record. */
+        WLDSF_UNCERTAIN = 0x0100,
+
+        /** Symbol found during library search.
+         * If this is an attribute to a symbol of the WLDSF_IMPORT type, the
+         * symbol is actually kind of weak.
+         */
+        WLDSF_LIBSEARCH = 0x0200,
+
+        /** Weak symbol.
+         * This symbol doesn't need to be resolved (if WLDSF_UNDEF), or
          * it may be overridden by a EXTDEF with no WKEXT.
          * If this is an weak undefined symbol (extern weak, local default)
          * pWeakDefault Will point at it.
          */
-        WLDSF_WEAK      = 0x0100,
-
-        /** Uncertain undefined symbol.
-         * We're still processing the module containing this and the uncertainty
-         * we're facing is that a WLDSF_UNDEF may changed to an WLDSF_WKEXT 
-         * upon encountering a WKEXT COMENT record. */
-        WLDSF_UNCERTAIN = 0x0200,
-
-
-        /** Import symbol. 
-         * This symbol is imported. */
-        WLDSF_IMPORT    = 0x0400,
-        /** Exported symbol. 
-         * This symbol is to be exported. */
-        WLDSF_EXPORT    = 0x0800,
+        WLDSF_WEAK      = 0x0400,
+
         /** Alias symbol.
          * This symbol is an alias for another symbol. pAliasFor will be set. */
-        WLDSF_ALIAS     = 0x1000,
-    }                   eFlags;
+        WLDSF_ALIAS     = 0x0800,
+
+        /** Exported symbol.
+         * This symbol is to be exported. */
+        WLDSF_EXPORT    = 0x1000,
+
+    }                   fFlags;
 
     /** The module this symbol is defined in. */
     PWLDMOD             pMod;
 
-
-    /** Import module - only if WLDSF_IMPORT is set. */
+    /** @group Import Attributes
+     * Valid when type is WLDSF_IMPORT.
+     * @{ */
+    /** Import module. */
     const char*         pszImpMod;
-
-    /** Import Ordinal (WLDSF_IMPORT). 
+    /** Import Ordinal (WLDSF_IMPORT).
      * 0 means no ordinal. */
-    unsigned            iImpOrd;
-
-
-    /** Export flags */
-    struct 
-    {
-        unsigned    fResidentName : 1;  /* Put name in resident or non resident table. */
-        unsigned    fNoName : 1;        /* No name at all. */
-        unsigned    fNoData : 1;        /* ?? */
-        unsigned    cParams;            /* callgate stuff, # of words to push */
-    }                   fExport;
-
-    /** Import Ordinal (WLDSF_EXPORT). 
-     * 0 means no ordinal. */
-    unsigned            iExpOrd;
-
-
-    /** Symbol this is an alias for. */
-    struct wldsym *     pAliasFor;
-
-    /** Weak default resolution. 
-     * If this symbol in state WLDSF_WKEXT or have to WLDSF_WEAK flag set this
-     * member indicates a default resolution for the symbol. For WLDSF_WEAK 
-     * this only make sense if the state is WLDSF_UNDEF.
+    unsigned            uImpOrd;
+    /** @} */
+
+    /** Weak default resolution.
+     * Valid if the symbol is of type WLDSF_WKEXT or have the WLDSF_WEAK flag set.
+     * Indicates a default resolution for the symbol.
+     * For WLDSF_WEAK this only make sense if the type is WLDSF_UNDEF.
      */
     struct wldsym *     pWeakDefault;
+
+    /** Symbol this is an alias for.
+     * Valid when WLDSF_ALIAS is set. */
+    struct wldsym *     pAliasFor;
+
+    /** @group Export Attributes
+     * Valid when WLDSF_EXPORT is set.
+     * @{ */
+    /** Export flags. */
+    enum
+    {
+        /** @group Name */
+        /** Name type mask. */
+        WLDSEF_NAMEMASK         = 0x03,
+        /** Default action depending on if it have an ordinal or not.
+         * If it have an ordinal it shall be non-resident, if it hasn't
+         * it shall be resident.
+         */
+        WLDSEF_DEFAULT          = 0x00,
+        /** The name shall be in the resident nametable. */
+        WLDSEF_RESIDENT         = 0x01,
+        /** The name shall be in the resident nametable. */
+        WLDSEF_NONRESIDENT      = 0x02,
+        /** The export shall only have ordinal. */
+        WLDSEF_NONAME           = 0x03,
+        /** @} */
+        /** no idea what this implies */
+        WLDSEF_NODATA           = 0x04
+    }                   fExport;
+    /** Export word count. */
+    unsigned            cExpWords;
+    /** Export Ordinal.
+     * 0 means no ordinal. */
+    unsigned            uExpOrd;
+    /** @} */
 
     /** Next node in the hash bucket. */
@@ -212,6 +252,6 @@
 } WLDSYMTAB, *PWLDSYMTAB;
 
- 
-/** 
+
+/**
  * Weak Pre-Linker Instance.
  */
@@ -236,7 +276,10 @@
 };
 typedef struct wld WLD;
- 
-
-/** @group OMF stuff 
+
+/** symAdd Action. */
+typedef enum { WLDSA_NEW, WLDSA_UP, WLDSA_OLD, WLDSA_ERR }  WLDSYMACTION, *PWLDSYMACTION;
+
+
+/** @group OMF stuff
  * @{ */
 
@@ -269,36 +312,68 @@
 extern void *xmalloc (size_t n);
 
-static unsigned     hash(const char* pszSym, unsigned cch);
+static void         wldInfo(const char *pszFormat, ...);
+static void         wldIntErr(PWLD pWld, PWLDMOD pMod, const char *pszFile, unsigned iLine, const char *pszFunction);
+static int          modError(PWLDMOD pMod, const char *pszFormat, ...);
+static void         modWarn(PWLDMOD pMod, const char *pszFormat, ...);
 static FILE *       modOpen(PWLDMOD pMod);
 static void         modClose(PWLDMOD pMod);
 
+static inline unsigned hash(const char* pszSym, unsigned cch);
+static PWLDSYM      symAdd(PWLD pWld, PWLDMOD pMod, unsigned fFlags, const char *pachName, int cchName,
+                           unsigned long ulValue, unsigned iSegment, PWLDSYMACTION peAction);
 
 
 /*******************************************************************************
-*  
+*
 *  H e l p e r s
 *  H e l p e r s
 *  H e l p e r s
-*  
+*
 *******************************************************************************/
 
-/** 
- * Calculate the hash value of a symbol.
- * @returns hash value.
- * @param   pszSym  Symbol to calculate it for.
- * @param   cch     Symbol length.
- */
-static unsigned     hash(const char* pszSym, unsigned cch)
-{
-    unsigned uHash = 0;
-    while (cch && *pszSym && *pszSym != '$')
-    {
-        uHash = uHash * 65599 + *pszSym;
-        pszSym++;
-        cch--;
-    }
-    uHash %= WLDSYM_HASH_SIZE;
-    return uHash;  
-}
+
+/**
+ * Put out a info message.
+ * @param   pszFormat   Format string.
+ * @param   ...         Format arguments.
+ */
+static void         wldInfo(const char *pszFormat, ...)
+{
+    va_list     args;
+    fprintf(stderr, "weakld: info: ");
+
+    va_start(args, pszFormat);
+    vfprintf(stderr, pszFormat, args);
+    va_end(args);
+    if (pszFormat[strlen(pszFormat) - 1] != '\n')
+        fputc('\n', stderr);
+}
+
+
+/**
+ * Internal error.
+ *
+ * @returns don't return, it aborts the process.
+ * @param   pWld        Pointer to linker instance (optional).
+ * @param   pMod        Pointe to module (optional).
+ * @param   pszFile     File name of the error.
+ * @param   iLine       Line number of the error.
+ * @param   pszFunction The function in which the error occured.
+ */
+static void         wldIntErr(PWLD pWld, PWLDMOD pMod, const char *pszFile, unsigned iLine, const char *pszFunction)
+{
+    fprintf(stderr, "\nweakld: ");
+    if (pMod)
+    {
+        if (pMod->pLib)
+            fprintf(stderr, "%s(%s) ", pMod->pLib->pszLibName, pMod->pszModName);
+        else
+            fprintf(stderr, "%s ", pMod->pszModName);
+    }
+    fprintf(stderr, "internal error!");
+    fprintf(stderr, "file: %s  line: %d  function: %s\n", pszFile, iLine, pszFunction);
+    abort();
+}
+
 
 /**
@@ -308,5 +383,5 @@
  * @param   ...         Format arguments.
  */
-static void     modError(PWLDMOD pMod, const char *pszFormat, ...)
+static int      modError(PWLDMOD pMod, const char *pszFormat, ...)
 {
     va_list     args;
@@ -321,4 +396,5 @@
     if (pszFormat[strlen(pszFormat) - 1] != '\n')
         fputc('\n', stderr);
+    return -1;
 }
 
@@ -379,15 +455,15 @@
     /* Position the stream at the start of the module. */
     if (!pMod->phFile)
-        modErrro(pMod, "failed to reopen.");
+        modError(pMod, "failed to reopen.");
     else
     {
         if (fseek(pMod->phFile, pMod->off, SEEK_SET))
         {
-            modErrro(pMod, "failed to seek to module start (%#x).", pMod->off);
+            modError(pMod, "failed to seek to module start (%#x).", pMod->off);
             modClose(pMod);
             return NULL;
         }
     }
-        
+
     return pMod->phFile;
 }
@@ -409,28 +485,434 @@
 
 
+
+
+
+/**
+ * Calculate the hash value of a symbol.
+ * @returns hash value.
+ * @param   pszSym  Symbol to calculate it for.
+ * @param   cch     Symbol length.
+ */
+static inline unsigned hash(const char* pszSym, unsigned cch)
+{
+    unsigned uHash = 0;
+    while (cch && *pszSym && *pszSym != '$')
+    {
+        uHash = uHash * 65599 + *pszSym;
+        pszSym++;
+        cch--;
+    }
+    uHash %= WLDSYM_HASH_SIZE;
+    return uHash;
+}
+
+/**
+ * Adds a symbol.
+ *
+ * Actually if the symbol exists we'll perform any required symbol 'merger' and
+ * either fail due to symbol errors or return the 'merged' one.
+ *
+ * We'll simply return existing symbol when:
+ *      1. adding a UNDEF where a PUBLIC or COMM exists.
+ *      2. adding a WKEXT where a PUBLIC or COMM exists.
+ *      3. adding a WKEXT where a UNDEF which isn't UNCERTAIN exists.
+ *      4. adding a COMM where a !WEAK COMM exists. (todo value check)
+ *      5. adding a WEAK PUBLIC or WEAK COMM where a PUBLIC or COMM exists.
+ *
+ * We'll warn and return existing symbol when:
+ *      1. adding a IMPORT LIBSEARCH where a PUBLIC or COMM exists.
+ *
+ * We'll return upgraded existing symbol when:
+ *      1. adding a PUBLIC or COMM where a UNDEF or WKEXT exists.
+ *      2. adding a !WEAK PUBLIC or !WEAK COMM where a WEAK PUBLIC or WEAK COMM exists.
+ *      3. adding a !WEAK UNDEF where a WEAK UNDEF exists.
+ *      4. adding a UNDEF where a WKEXT exists.
+ *
+ * We'll warn and upgraded existing symbol when:
+ *      1. adding a PUBLIC or COMM where a IMPORT LIBSEARCH exists.
+ *
+ * The rest is failures.
+ *
+ * There migth be errors in the algorithm. Like adding the same import twice
+ * shouldn't harm anybody, but it's unlikely and it requires quite some extra parameters.
+ * Also the caller must resolve any conflicting exports (which normally only yields
+ * warnings anyway it seems).
+ *
+ * @returns Pointer to symbold.
+ * @returns NULL on failure.
+ * @param   pWld        Linker instance.
+ * @param   pMod        Module the the symbol is defined in.
+ * @param   fFlags      Symbol flags.
+ *                      All the flags in WLDSF_TYPEMASK, WLDSF_WEAK and WLDSF_LIBSEARCH.
+ *                      WLDSF_EXPORT isn't handled and should not be defined.
+ *                      WLDSF_ALIAS and WLDSF_UNCERTAIN is ignored as they have no
+ *                      sideeffects when resolving symbols.
+ * @param   pachName    Pointer to symbol name.
+ * @param   cchName     Length to add, use -1 if zeroterminated.
+ * @param   ulValue     Value of the symbol (if it's relevant for this kind of symbol). (ignored)
+ * @param   iSegment    Segment of pMod in which this symbol is defined (only if relevant). (ignored)
+ * @param   pflAction   What we actually did.
+ *                      WLDSA_NEW, WLDSA_UP, WLDSA_OLD, WLDSA_ERR.
+ */
+static PWLDSYM      symAdd(PWLD pWld, PWLDMOD pMod, unsigned fFlags, const char *pachName, int cchName,
+                           unsigned long ulValue, unsigned iSegment, PWLDSYMACTION peAction)
+{
+    PWLDSYM     pSym;                   /* The symbol. */
+    unsigned    uHash;                  /* The symbol name hash. */
+    const char *pszName;                /* The symbol name in the string pool */
+    int         cchNameWeak = 0;        /* Indicator and length of the weak name. (0 if not weak) */
+    /* general stuff */
+    const char *    pach;
+
+    if (peAction)
+        *peAction = WLDSA_ERR;
+    if (cchName < 0)
+        cchName = strlen(pachName);
+
+    /* adjust namelength / check for weak name / hash name */
+    pach = pachName + cchName - 2;      /* "$w$" */
+    while (pach-- > pachName)
+        if (    pach[0] == '$'
+            &&  pach[1] == 'w'
+            &&  pach[2] == '$')
+        {
+            cchNameWeak = cchName;
+            cchName = pachName - pach;
+            fFlags |= WLDSF_WEAK;
+            /* If WKEXT we'll upgrade it to weak undefined. (yeah, big deal?) */
+            if ((fFlags & WLDSF_TYPEMASK) == WLDSF_WKEXT)
+                fFlags = (fFlags & ~WLDSF_TYPEMASK) | WLDSF_UNDEF;
+            break;
+        }
+    uHash = hash(pachName, cchName);
+    pszName = (pWld->fFlags & WLDC_CASE_INSENSITIVE ? strpool_addn : strpool_addnu)(pWld->pStrMisc, pachName, cchName);
+
+    /* search for existing symbol  */
+    pSym = pWld->Global.ap[uHash];
+    while (pSym && pSym->pszName == pszName)
+        pSym = pSym->pHashNext;
+
+    if (!pSym)
+    {
+        /*
+         * new symol - this is easy!
+         */
+        pSym = xmalloc(sizeof(*pSym));
+        memset(pSym, 0, sizeof(*pSym));
+        pSym->fFlags = fFlags;
+        pSym->pszName = pszName;
+        if (SYM_IS_DEFINED(pSym->fFlags))
+            pSym->pMod = pMod;
+        if (cchNameWeak)
+        {
+            pSym->pszWeakName = strpool_addn(pWld->pStrMisc, pachName, cchNameWeak);
+            pSym->fFlags |= WLDSF_WEAK;
+            WLDINFO(pWld, ("Weak symbol '%s'.", pSym->pszWeakName));
+        }
+        pSym->pHashNext = pWld->Global.ap[uHash];
+        pWld->Global.ap[uHash] = pSym;
+        if (peAction) *peAction = WLDSA_NEW;
+    }
+    else
+    {   /* found existing symbol - more complex... */
+
+        /*
+         * We'll simply return existing symbol when:
+         *      1. adding a UNDEF where a PUBLIC or COMM exists.
+         *      2. adding a WKEXT where a PUBLIC or COMM exists.
+         *      3. adding a WKEXT where a UNDEF which isn't UNCERTAIN exists.
+         *      4. adding a COMM where a !WEAK COMM exists. (todo value check)
+         *      5. adding a WEAK PUBLIC or WEAK COMM where a PUBLIC or COMM exists.
+         */
+        if ( (     /* 1 */
+                (fFlags & WLDSF_TYPEMASK) == WLDSF_UNDEF
+             && ((pSym->fFlags & WLDSF_TYPEMASK) == WLDSF_PUBLIC || (pSym->fFlags & WLDSF_TYPEMASK) == WLDSF_COMM)
+            ) || ( /* 2 */
+                (fFlags & WLDSF_TYPEMASK) == WLDSF_WKEXT
+             && ((pSym->fFlags & WLDSF_TYPEMASK) == WLDSF_PUBLIC || (pSym->fFlags & WLDSF_TYPEMASK) == WLDSF_COMM)
+            ) || ( /* 3 */
+                (fFlags & WLDSF_TYPEMASK) == WLDSF_WKEXT
+             && (pSym->fFlags & (WLDSF_TYPEMASK | WLDSF_UNCERTAIN)) == WLDSF_UNDEF
+            ) || ( /* 4 */
+                (fFlags & WLDSF_TYPEMASK) == WLDSF_COMM
+             && (pSym->fFlags & (WLDSF_TYPEMASK | WLDSF_WEAK)) == WLDSF_COMM
+            ) || ( /* 5 */
+                ((fFlags & (WLDSF_TYPEMASK | WLDSF_WEAK)) == (WLDSF_PUBLIC | WLDSF_WEAK) || (fFlags & (WLDSF_TYPEMASK | WLDSF_WEAK)) == (WLDSF_COMM | WLDSF_WEAK))
+             && ((pSym->fFlags & WLDSF_TYPEMASK) == WLDSF_PUBLIC || (pSym->fFlags & WLDSF_TYPEMASK) == WLDSF_COMM)
+            ))
+        {
+            if (peAction) *peAction = WLDSA_OLD;
+        }
+        /*
+         * We'll warn and return existing symbol when:
+         *      1. adding a IMPORT LIBSEARCH where a PUBLIC or COMM exists.
+         */
+        else
+        if (    (fFlags & (WLDSF_TYPEMASK | WLDSF_LIBSEARCH)) == (WLDSF_IMPORT | WLDSF_LIBSEARCH)
+             && ((pSym->fFlags & WLDSF_TYPEMASK) == WLDSF_PUBLIC || (pSym->fFlags & WLDSF_TYPEMASK) == WLDSF_COMM)
+            )
+        {
+            modWarn(pMod, "Ignoring import '%s' as it's defined already.", pszName);
+            if (peAction) *peAction = WLDSA_OLD;
+        }
+        /*
+         * We'll return upgraded existing symbol when:
+         *      1. adding a PUBLIC or COMM where a UNDEF or WKEXT exists.
+         *      2. adding a !WEAK PUBLIC or !WEAK COMM where a WEAK PUBLIC or WEAK COMM exists.
+         *      3. adding a !WEAK UNDEF where a WEAK UNDEF exists.
+         *      4. adding a UNDEF where a WKEXT exists.
+         */
+        else
+        if ( (     /* 1 */
+                ((fFlags & WLDSF_TYPEMASK) == WLDSF_PUBLIC || (fFlags & WLDSF_TYPEMASK) == WLDSF_COMM)
+            &&  ((pSym->fFlags & WLDSF_TYPEMASK) == WLDSF_WKEXT || (pSym->fFlags & WLDSF_TYPEMASK) == WLDSF_UNDEF)
+            ) || ( /* 2 */
+                ((fFlags & (WLDSF_TYPEMASK | WLDSF_WEAK)) == WLDSF_PUBLIC || (fFlags & (WLDSF_TYPEMASK | WLDSF_WEAK)) == WLDSF_COMM)
+            &&  ((pSym->fFlags & (WLDSF_TYPEMASK | WLDSF_WEAK)) == (WLDSF_PUBLIC | WLDSF_WEAK) || (pSym->fFlags & (WLDSF_TYPEMASK | WLDSF_WEAK)) == (WLDSF_COMM | WLDSF_WEAK))
+            ) || ( /* 3 */
+                (fFlags & (WLDSF_TYPEMASK | WLDSF_WEAK)) == WLDSF_UNDEF
+            &&  (pSym->fFlags & (WLDSF_TYPEMASK | WLDSF_WEAK)) == (WLDSF_UNDEF | WLDSF_WEAK)
+            ) || ( /* 4 */
+                (fFlags & WLDSF_TYPEMASK) == WLDSF_UNDEF
+            &&  (pSym->fFlags & WLDSF_TYPEMASK) == WLDSF_WKEXT
+            ))
+        {
+            if (!(pSym->fFlags & WLDSF_WEAK) && (fFlags & WLDSF_WEAK) && cchNameWeak)
+            {   /* the symbol is upgraded to a weak one - there probably won't be a name though. */
+                pSym->pszWeakName = strpool_addn(pWld->pStrMisc, pachName, cchNameWeak);
+            }
+            pSym->fFlags = (pSym->fFlags & ~(WLDSF_TYPEMASK | WLDSF_WEAK | WLDSF_UNCERTAIN | WLDSF_LIBSEARCH)) | fFlags;
+            if (peAction) *peAction = WLDSA_UP;
+        }
+        /*
+         * We'll warn and upgraded existing symbol when:
+         *      1. adding a PUBLIC or COMM where a IMPORT LIBSEARCH exists.
+         */
+        else
+        if (   ((fFlags & WLDSF_TYPEMASK) == WLDSF_PUBLIC || (fFlags & WLDSF_TYPEMASK) == WLDSF_COMM)
+            && (pSym->fFlags & (WLDSF_TYPEMASK | WLDSF_LIBSEARCH)) == (WLDSF_IMPORT | WLDSF_LIBSEARCH)
+            )
+        {
+            modWarn(pMod, "Ignoring imported symbol '%s' as it's being defined here.", pszName);
+
+            if (!(pSym->fFlags & WLDSF_WEAK) && (fFlags & WLDSF_WEAK) && cchNameWeak)
+            {   /* the symbol is upgraded to a weak one - there probably won't be a name though. */
+                pSym->pszWeakName = strpool_addn(pWld->pStrMisc, pachName, cchNameWeak);
+            }
+            pSym->fFlags = (pSym->fFlags & ~(WLDSF_TYPEMASK | WLDSF_WEAK | WLDSF_UNCERTAIN | WLDSF_LIBSEARCH)) | fFlags;
+            if (peAction) *peAction = WLDSA_UP;
+        }
+        /*
+         * That's all, now it's just error left.
+         *
+         * (Afraid we might end up here without wanting to a few times before
+         *  squashing all the bugs in the algorithm.)
+         */
+        else
+        {
+            modError(pMod, "Duplicate symbol '%s'.", pszName);
+            if (pSym->pMod)
+                modError(pSym->pMod, "Previous symbol defined in this module.");
+            wldInfo("fFlags new 0x%04x  fFlags old 0x%04x.", fFlags, pSym->fFlags);
+            pSym = NULL;
+        }
+    }
+
+    return pSym;
+}
+
+
+
+/**
+ * Adds an import symbol to the linking.
+ *
+ * @returns see symAdd()
+ * @param   pWld        Pointer to linker instance.
+ * @param   pMod        Pointer to module
+ * @param   fLibSearch  Set if we're doing library search at this time.
+ * @param   pachIntName Internal name, the one which can be referenced in this module.
+ * @param   cchIntName  Length of that name. -1 if zero terminated string.
+ * @param   pachModName Module name where the export should be resolved on load time.
+ * @param   cchModName  Length of that name. -1 if zero terminated string.
+ * @param   uOrdinal    The ordinal it's exported with from the module.
+ *                      0 if exported by the name pachIntName represent.
+ */
+PWLDSYM symAddImport(PWLD pWld, PWLDMOD pMod, int fLibSearch,
+                     const char *pachIntName, int cchIntName,
+                     const char *pachModName, int cchModName,
+                     unsigned uOrdinal)
+{
+    WLDSYMACTION    eAction;
+    PWLDSYM         pSym;
+    const char *    pszImpMod;
+
+    pSym = symAdd(pWld, pMod, WLDSF_IMPORT | (fLibSearch ? WLDSF_LIBSEARCH : 0),
+                  pachIntName, cchIntName, 0, 0, &eAction);
+    if (!pSym)
+        return NULL;
+
+    pszImpMod = strpool_addnu(pWld->pStrMisc, pachModName, cchModName);
+    switch (eAction)
+    {
+        case WLDSA_NEW:
+            pSym->pszImpMod = pszImpMod;
+            pSym->uImpOrd = uOrdinal;
+            break;
+
+        case WLDSA_OLD:
+        {   /* verify that the name matches */
+            if ((pSym->fFlags & WLDSF_TYPEMASK) == WLDSF_IMPORT)
+            {
+                if (!pSym->pszImpMod)
+                {
+                    pSym->pszImpMod = pszImpMod;
+                    pSym->uImpOrd = uOrdinal;
+                }
+                else
+                {
+                    if (    pSym->pszImpMod != pszImpMod
+                        &&  pSym->uImpOrd != uOrdinal)
+                    {
+                        modWarn(pMod, "Existing import '%s' have different module name than the new ('%s' != '%s') and different ordinal (%d != %d).",
+                                pSym->pszName, pSym->pszImpMod, pszImpMod, pSym->uImpOrd, uOrdinal);
+                    }
+                    else if (pSym->uImpOrd != uOrdinal)
+                    {
+                        modWarn(pMod, "Existing import '%s' have different ordinal (%d != %d).",
+                                pSym->pszName, pSym->uImpOrd, uOrdinal);
+                    }
+                    else if (pSym->pszImpMod != pszImpMod)
+                    {
+                        modWarn(pMod, "Existing import '%s' have different module name than the new ('%s' != '%s').",
+                                pSym->pszName, pSym->pszImpMod, pszImpMod);
+                    }
+                }
+            }
+            /* else: no need to complain, symAdd already did that. */
+            break;
+        }
+
+        case WLDSA_UP:
+        default:
+            WLDINTERR(pWld, pMod);
+    }
+
+    return pSym;
+}
+
+
+/**
+ * Adds(/Marks) an exported symbol.
+ *
+ * @returns see symAdd()
+ * @param   pWld        Pointer to linker instance.
+ * @param   pMod        Pointer to module
+ * @param   fLibSearch  Set if we're doing library search at this time.
+ * @param   fExport     Export flags (WLDSEF_*).
+ * @param   cExpWords   Number of words to push on the stack if this
+ *                      export is a call gate.
+ * @param   pachExpName Exported name.
+ * @param   cchExpName  Length of that name. -1 if zero terminated string.
+ * @param   pachIntName Internal name. NULL or with cchIntName == 0 if the same
+ *                      as the exported one.
+ * @param   cchIntName  Length of that name. -1 if zero terminated string.
+ *                      0 if the internal name is the same and the exported one.
+ * @param   uOrdinal    The ordinal it's exported with
+ *                      0 if exported by the name pachIntName represent.
+ */
+static PWLDSYM symAddExport(PWLD pWld, PWLDMOD pMod, int fLibSearch,
+                            unsigned    fExport,
+                            unsigned    cExpWords,
+                            const char *pachExpName, int cchExpName,
+                            const char *pachIntName, int cchIntName,
+                            unsigned uOrdinal)
+{
+    PWLDSYM         pSym;
+
+    /* set default name */
+    if (!pachIntName || !cchIntName)
+    {
+        pachExpName = pachIntName;
+        cchExpName = cchIntName;
+    }
+
+    /*
+     * Add external name.
+     */
+    pSym = symAdd(pWld, pMod, WLDSF_UNDEF | (fLibSearch ? WLDSF_LIBSEARCH : 0),
+                  pachExpName, cchExpName, 0, 0, NULL);
+    if (!pSym)
+        return NULL;
+
+    /*
+     * Is the exported symbol already exported?
+     */
+    if (pSym->fFlags & WLDSF_EXPORT)
+    {
+        /* Just warn and ignore */
+        modWarn(pMod, "Export '%s' is already defined.", pSym->pszName);
+    }
+    else
+    {
+        PWLDSYM     pSymAlias;
+
+        /*
+         * Add internal name.
+         */
+        pSymAlias = symAdd(pWld, pMod, WLDSF_UNDEF | (fLibSearch ? WLDSF_LIBSEARCH : 0),
+                           pachIntName, cchIntName, 0, 0, NULL);
+        if (!pSymAlias)
+            return NULL;
+        if (pSymAlias != pSym && (pSym->fFlags & WLDSF_ALIAS) && pSym->pAliasFor != pSymAlias)
+        {
+            modError(pMod, "Can't export an alias!.");
+            pSym = NULL;
+        }
+        else
+        {
+            if (pSym->pAliasFor != pSymAlias)
+            {
+                pSym->fFlags |= WLDSF_ALIAS;
+                pSym->pAliasFor = pSymAlias;
+            }
+            pSym->fExport   = fExport;
+            pSym->cExpWords = cExpWords;
+            pSym->uExpOrd   = uOrdinal;
+        }
+    }
+
+    return pSym;
+}
+
 /**
  * Reads an OMF module from a file.
  *
- * This may be part of a library file so, we'll only read from THEADR to 
+ * This may be part of a library file so, we'll only read from THEADR to
  * past the first MODEND or the Pass 1 comment record.
- * The function will return the module stream positioned after the last 
+ * The function will return the module stream positioned after the last
  * record it read.
  *
  * @returns 0 on success.
  * @returns non zero on failure.
- * @param   pWld    Pointer to linker instance.
- * @param   pMod    Pointer to module
- */
-static unsigned     pass1ReadOMFMod(PWLD pWld, PWLDMOD pMod)
-{
+ * @param   pWld        Pointer to linker instance.
+ * @param   pMod        Pointer to module
+ * @param   fLibSearch  Set if we're doing library search at this time.
+ */
+static unsigned     pass1ReadOMFMod(PWLD pWld, PWLDMOD pMod, int fLibSearch)
+{
+    OMFREC          OmfRec = {0,0};
     FILE *          phFile;             /* Input file. */
-    PWLDSYM         papExts[] = NULL;   /* Pointer to an array of EXTDEFs (as they appear) */
+    PWLDSYM *       papExts = NULL;     /* Pointer to an array of EXTDEFs (as they appear) */
                                         /* We need them for the WKEXT processing. */
     int             cExts = 0;          /* Number of Entries in papExts. */
     int             fFirst = 1;         /* First record indicator. */
     /* generic stuff we'll use alot with not status associated. */
-    int             cch;                
+    int             cch;
     PWLDSYM         pSym;
     PWLDSYM         pSym2;
+    int             i;
+    unsigned long   ul;
+    unsigned short  us;
+    unsigned char   uch, uch2, uch3;
 
 
@@ -442,7 +924,6 @@
     for (;;)
     {
-        OMFREC          OmfRec;             
         unsigned char   achBuffer[OMF_MAX_REC + 8];
-        union 
+        union
         {
             unsigned char *     puch;
@@ -452,4 +933,5 @@
             unsigned long *     pul;
             signed long *       pl;
+            void *              pv;
         } u, u1, u2, u3;
         /** macro for getting a OMF index out of the buffer */
@@ -476,5 +958,5 @@
             }
         }
-    
+
         /* Read or skip the record. */
         switch (OmfRec.chType)
@@ -482,15 +964,15 @@
             /* done */
             case MODEND: case MODEND | REC32:
-            case LIBEND: 
+            case LIBEND:
                 fseek(phFile, OmfRec.cb, SEEK_CUR);
                 goto done_skip;
             /* read */
-            case EXTDEF: case EXTDEF | REC32: 
-            case PUBDEF: case PUBDEF | REC32: 
+            case EXTDEF: case EXTDEF | REC32:
+            case PUBDEF: case PUBDEF | REC32:
             case ALIAS:  case ALIAS  | REC32:
-            case COMDEF: case COMDEF | REC32: 
-            case COMDAT: case COMDAT | REC32: 
-            case COMENT: case COMENT | REC32: 
-            case LIBHDR: 
+            case COMDEF: case COMDEF | REC32:
+            case COMDAT: case COMDAT | REC32:
+            case COMENT: case COMENT | REC32:
+            case LIBHDR:
                 break;
             /* skip */
@@ -502,5 +984,5 @@
         {
             modError(pMod, "read error. (offset ~= %#x)", ftell(phFile));
-            goto failure;             
+            goto failure;
         }
 
@@ -508,5 +990,5 @@
         switch (OmfRec.chType)
         {
-            case COMENT: case COMENT | REC32: 
+            case COMENT: case COMENT | REC32:
                 switch (*++u.pch)
                 {
@@ -514,8 +996,8 @@
                          goto done_noskip;
                     case CLASS_WKEXT:
-                    {   /* This is a bit tricky, we need to have an indexable array 
-                         * of the extdefs for this module. In addition we'll need to 
+                    {   /* This is a bit tricky, we need to have an indexable array
+                         * of the extdefs for this module. In addition we'll need to
                          * make sure we don't mark an EXTDEF from another module as
-                         * weak. 
+                         * weak.
                          */
                         while (OMF_MORE())
@@ -523,22 +1005,25 @@
                             int iWeak = OMF_GETINDEX();
                             int iDefault = OMF_GETINDEX();
-                            if (   iWeak     >= cExts 
+                            if (   iWeak     >= cExts
                                 || iDefault  >= cExts
                                 || !papExts[iWeak]
                                 || !papExts[iDefault])
+                            {
                                 modError(pMod, "Invalid WKEXT record.");
-                            if (papExts[iWeak]->eFlags & WLDSF_UNCERTAIN)
+                                goto failure;
+                            }
+                            if ((papExts[iWeak]->fFlags & (WLDSF_TYPEMASK | WLDSF_UNCERTAIN)) == (WLDSF_UNDEF | WLDSF_UNCERTAIN))
                             {
-                                papExts[iWeak]->eFlags = (papExts[iWeak]->eFlags & ~WLDSF_STATEMASK) | WLDSF_WKEXT;
+                                papExts[iWeak]->fFlags = (papExts[iWeak]->fFlags & ~(WLDSF_TYPEMASK | WLDSF_UNCERTAIN)) | WLDSF_WKEXT;
                                 papExts[iWeak]->pWeakDefault = papExts[iDefault];
                             }
-                            else if (   (papExts[iWeak]->eFlags & WLDSF_STATEMASK) == WLDSF_WKEXT
+                            else if (   (papExts[iWeak]->fFlags & WLDSF_TYPEMASK) == WLDSF_WKEXT
                                      &&  papExts[iWeak]->pWeakDefault != papExts[iDefault])
-                                modWarn(pMod, "WKEXT '%s' allready declared with '%s' and not '%s' as default.", 
+                                modWarn(pMod, "WKEXT '%s' already declared with '%s' and not '%s' as default.",
                                         papExts[iWeak]->pszName, papExts[iWeak]->pWeakDefault->pszName, papExts[iDefault]->pszName);
                         }
                         break;
                     }
-                    
+
                     case CLASS_OMFEXT:
                     {
@@ -549,18 +1034,20 @@
                             case OMFEXT_IMPDEF:
                             {
-                                int fOrd = OMF_BYTE();
-                                cch = OMF_BYTE();
-                                pSym = symNew(pWld, WLDSF_STRONG | WLDSF_IMPORT, u.pch, cch);
+                                uch = OMF_BYTE();               /* flags */
+                                u1 = u; u.pch += 1 + *u.puch;   /* internal name */
+                                u2 = u; u.pch += 1 + *u.puch;   /* module name */
+                                ul = 0;                         /* ordinal */
+                                if (uch & 1)
+                                    ul = OMF_WORD();
+
+                                pSym = symAddImport(pWld, pMod, fLibSearch,
+                                                    u1.pch + 1, *u1.puch,
+                                                    u2.pch + 1, *u2.puch,
+                                                    ul);
                                 if (!pSym) goto failure;
-                                u.pch += cch;
-                                cch = OMF_BYTE();
-                                pSym->pszImpMod = strpool_addn(pWld->pStrMisc, u.pch, cch);
-                                u.pch += cch;
-                                if (fOrd)
-                                    pSym->iImpOrd = OMF_WORD();
                                 break;
                             }
 
-                            /* 
+                            /*
                              * Export definition.
                              * If it have an internal name the exported name will become
@@ -569,44 +1056,30 @@
                             case OMFEXT_EXPDEF:
                             {
-                                u1 = u; u.pch++;
-                                u2 = u; u.pch+ = 1 + *u2.pch;
-                                u3 = u; u.pch+ = 1 + *u3.pch;
-                                
-                                pSym2 = NULL;
-                                if (*u3.pch)
-                                {
-                                    pSym2 = symNew(pWld, WLDSF_UNDEF, u3.pch + 1, *u3.pch);
-                                    if (!pSym2) goto failure;
-                                    pSym = symNew(pWld, WLDSF_STRONG | WLDSF_ALIAS | WLDSF_EXPORT, u2.pch + 1, *u2.pch);
-                                    if (!pSym) goto failure;
-                                    pSym->pAliasFor = pSym2;
-                                }
-                                else
-                                {
-                                    pSym = symNew(pWld, WLDSF_UNDEF | WLDSF_EXPORT, u2.pch + 1, *u2.pch);
-                                    if (!pSym) goto failure;
-                                }
+                                u1 = u; u.pch++;                /* flags */
+                                u2 = u; u.pch += 1 + *u.puch;   /* exported name */
+                                u3 = u; u.pch += 1 + *u.puch;   /* internal name */
+                                ul = 0;                         /* ordinal */
                                 if (*u1.pch & 0x80)
-                                    pSym->iExpOrd = GET_BYTE();
-                                if (*u1.pch & 0x40)
-                                    pSym->fExport.fResidentName = 1;
-                                
-
+                                    pSym->uExpOrd = OMF_BYTE();
+                                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,
+                                                    ul);
+                                if (!pSym) goto failure;
                                 break;
                             }
                         }
-
                     }
-
-                }
+                } /* comment class */
                 break;
 
             case EXTDEF: case EXTDEF | REC32:
             {
-
                 break;
             }
 
-            case PUBDEF: case PUBDEF | REC32: 
+            case PUBDEF: case PUBDEF | REC32:
             {
                 break;
@@ -618,10 +1091,10 @@
             }
 
-            case COMDEF: case COMDEF | REC32: 
+            case COMDEF: case COMDEF | REC32:
             {
                 break;
             }
 
-            case COMDAT: case COMDAT | REC32: 
+            case COMDAT: case COMDAT | REC32:
             {
                 break;
@@ -647,5 +1120,5 @@
     /* Make all the EXTDEFs uncertain. */
     for (i = 0; i < cExts; i++)
-        papExts[i]->eFlags &= ~WLDSF_UNCERTAIN;
+        papExts[i]->fFlags &= ~WLDSF_UNCERTAIN;
 
     return 0;
@@ -661,9 +1134,9 @@
 
 /*******************************************************************************
-*  
+*
 *  P u b l i c   I n t e r f a c e
 *  P u b l i c   I n t e r f a c e
 *  P u b l i c   I n t e r f a c e
-*  
+*
 *******************************************************************************/
 
@@ -680,5 +1153,5 @@
 {
     PWLD    pWld = xmalloc(sizeof(*pWld));
-    
+
     /* initiate it */
     memset(pWld, 0, sizeof(*pWld));
@@ -723,10 +1196,10 @@
  * @returns some unexplainable randomly picked number on failure.
  * @param   pWld    Linker instance to destroy.
- * @param   phFile  File handle to pszName. 
+ * @param   phFile  File handle to pszName.
  * @param   pszName Object file to add. This may be an OMF library too,
  *                  but that only means that all it's content is to be
- *                  linked in as if they have been all specified on the 
+ *                  linked in as if they have been all specified on the
  *                  commandline.
- * @remark  Don't call wld_add_object after wld_add_library() 
+ * @remark  Don't call wld_add_object after wld_add_library()
  *          or wld_generate_weaklib()!
  */
@@ -759,5 +1232,5 @@
         *pWld->ppObjsAdd = pMod;
         pWld->ppObjsAdd = &pMod->pNext;
-        rc = pass1ReadOMFMod(pWld, pMod);
+        rc = pass1ReadOMFMod(pWld, pMod, 0);
     }
     else if (OmfRec.chType == LIBHDR)
@@ -783,5 +1256,5 @@
                     fprintf(stderr, "weakld: info: adding library member '%s'.\n", achModName);
                 }
-                rc = pass1ReadOMFMod(pWld, pMod);
+                rc = pass1ReadOMFMod(pWld, pMod, 0);
                 if (rc)
                     break;
@@ -817,6 +1290,6 @@
  *                  The handle may be closed on exit, or latest when
  *                  we destroy the linker.
- * @param   pszName Definition file to add. 
- * @remark  Don't call wld_add_deffile after wld_add_library() 
+ * @param   pszName Definition file to add.
+ * @remark  Don't call wld_add_deffile after wld_add_library()
  *          or wld_generate_weaklib()!
  */
@@ -868,5 +1341,5 @@
 
 /**
- * Generates a object file containing alias for resolving the weak 
+ * Generates a object file containing alias for resolving the weak
  * symbol references in the linked executable.
  * The filename of the object will be generated, but of course it
Index: trunk/src/emx/src/emxomf/weakld.h
===================================================================
--- trunk/src/emx/src/emxomf/weakld.h	(revision 489)
+++ trunk/src/emx/src/emxomf/weakld.h	(revision 491)
@@ -31,12 +31,14 @@
 struct wld;
 typedef struct wld * PWLD;
- 
+
 /** wld_create() flags. */
 enum wld_create_flags
 {
     /** Verbose */
-    WLDC_VERBOSE        = 1,    
+    WLDC_VERBOSE        = 1,
     /** Skip extended dictionary of libraries. */
-    WLDC_NO_EXTENDED_DICTIONARY_SEARCH = 2,    
+    WLDC_NO_EXTENDED_DICTIONARY_SEARCH = 2,
+    /** Case in-sensitive symbol resolution. */
+    WLDC_CASE_INSENSITIVE = 4,
 };
 
@@ -52,3 +54,3 @@
 int     wld_destroy(PWLD pWld);
 
-#endif 
+#endif
