Index: trunk/src/emx/src/emxomf/emxomfld.c
===================================================================
--- trunk/src/emx/src/emxomf/emxomfld.c	(revision 509)
+++ trunk/src/emx/src/emxomf/emxomfld.c	(revision 510)
@@ -477,5 +477,5 @@
   FILE *        phFile;
   char          cchname = strlen (pszname);
-  
+    
   /* Plain name first - the easist option */
   memcpy (pszfullname, pszname, cchname + 1);
@@ -512,5 +512,5 @@
           /* normalize the name */
           cch = pszend - psz;
-          strncpy(pszfullname, psz, pszend - psz);
+          memcpy(pszfullname, psz, pszend - psz);
           if (   pszfullname[cch-1] != '\\'
               && pszfullname[cch-1] != '/'
@@ -531,6 +531,6 @@
                     {
                       memcpy(pszfullname + cch, "lib", 3);
-                      memcpy(pszfullname + cch, pszname, cchname);
-                      strcpy(pszfullname + cch + cchname, papszexts[i]);
+                      memcpy(pszfullname + cch + 3, pszname, cchname);
+                      strcpy(pszfullname + cch + 3 + cchname, papszexts[i]);
                       phFile = fopen (pszfullname, "rb");
                       if (phFile)
@@ -578,4 +578,5 @@
         } /* foreach path in $LIB */
     }
+  strcpy(pszfullname, pszname);
   return NULL;
 }
Index: trunk/src/emx/src/emxomf/weakld.c
===================================================================
--- trunk/src/emx/src/emxomf/weakld.c	(revision 509)
+++ trunk/src/emx/src/emxomf/weakld.c	(revision 510)
@@ -54,4 +54,11 @@
 #define WLDINTERR(pWld, pMod)   wldIntErr(pWld, pMod, __FILE__, __LINE__, __FUNCTION__);
 
+#ifdef DEBUG
+
+#define SYMDBG(pSym, pszMsg)    symDbg(pSym, pszMsg);
+#else
+#define SYMDBG(pSym, pszMsg)    do {} while (0)
+#endif 
+
 
 /** Helpers for checking if a symbol is defined strongly. */
@@ -60,6 +67,4 @@
                                   || (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)
 
 
@@ -187,13 +192,28 @@
     PWLDMOD             pMod;
 
-    /** @group Import Attributes
-     * Valid when type is WLDSF_IMPORT.
-     * @{ */
-    /** Import module. */
-    const char*         pszImpMod;
-    /** Import Ordinal (WLDSF_IMPORT).
-     * 0 means no ordinal. */
-    unsigned            uImpOrd;
-    /** @} */
+    /** Per type data union */
+    union type_data
+    {
+        struct import_data
+        {
+            /** @group Import Attributes
+             * Valid when type is WLDSF_IMPORT.
+             * @{ */
+            /** Import module. */
+            const char*         pszImpMod;
+            /** Import Ordinal (WLDSF_IMPORT).
+             * 0 means no ordinal. */
+            unsigned            uImpOrd;
+            /** @} */
+        } import;
+
+        struct comm_data
+        {
+            /** Size of comm object */
+            signed long         cb;
+            /** Number of elements. */
+            signed long         cElements;
+        } comm;
+    } u;
 
     /** Weak default resolution.
@@ -313,6 +333,7 @@
 
 static void         wldInfo(const char *pszFormat, ...);
+static int          wldErr(PWLD pWld, 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 int          modErr(PWLDMOD pMod, const char *pszFormat, ...);
 static void         modWarn(PWLDMOD pMod, const char *pszFormat, ...);
 static FILE *       modOpen(PWLDMOD pMod);
@@ -320,6 +341,5 @@
 
 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);
+static void         symDbg(PWLDSYM pSym, const char *pszMsg);
 
 
@@ -350,4 +370,22 @@
 }
 
+/**
+ * Put out a info message.
+ * @param   pszFormat   Format string.
+ * @param   ...         Format arguments.
+ */
+static int          wldErr(PWLD pWld, const char *pszFormat, ...)
+{
+    va_list     args;
+    fprintf(stderr, "weakld: error: ");
+    
+    va_start(args, pszFormat);
+    vfprintf(stderr, pszFormat, args);
+    va_end(args);
+    if (pszFormat[strlen(pszFormat) - 1] != '\n')
+        fputc('\n', stderr);
+    return -1;
+}
+
 
 /**
@@ -383,5 +421,5 @@
  * @param   ...         Format arguments.
  */
-static int      modError(PWLDMOD pMod, const char *pszFormat, ...)
+static int      modErr(PWLDMOD pMod, const char *pszFormat, ...)
 {
     va_list     args;
@@ -455,10 +493,10 @@
     /* Position the stream at the start of the module. */
     if (!pMod->phFile)
-        modError(pMod, "failed to reopen.");
+        modErr(pMod, "failed to reopen.");
     else
     {
         if (fseek(pMod->phFile, pMod->off, SEEK_SET))
         {
-            modError(pMod, "failed to seek to module start (%#x).", pMod->off);
+            modErr(pMod, "failed to seek to module start (%#x).", pMod->off);
             modClose(pMod);
             return NULL;
@@ -485,5 +523,78 @@
 
 
-
+typedef int (*PFNSYMENUM)(PWLD pWld, PWLDSYM pSym, void *pvUser);
+
+/**
+ * Symbol enumerator.
+ *
+ * @returns return code from last pfnEnum call.
+ * @param   pWld    Weak Linker Instance.
+ * @param   pSymTab The symbol table to enumerate.
+ * @param   fFlags  The flags which (pSym->fFlags & fMask) much equal.
+ * @param   fMask   The flag mask.
+ * @param   pfnEnum Enumeration callback function.
+ * @param   pvUser  User arguments to pfnEnum.
+ */
+static int          symEnum(PWLD pWld, PWLDSYMTAB pSymTab, unsigned fFlags, unsigned fMask, PFNSYMENUM pfnEnum, void *pvUser)
+{
+    int         i;
+    PWLDSYM     pSym;
+    int         rc;
+
+    for (i = 0; i < sizeof(pSymTab->ap) / sizeof(pSymTab->ap[0]); i++)
+    {
+        for (pSym = pSymTab->ap[i]; pSym; pSym = pSym->pHashNext)
+        {
+            if ((pSym->fFlags & fMask) == fFlags)
+            {
+                rc = pfnEnum(pWld, pSym, pvUser);    
+                if (rc)
+                    return rc;
+            }
+        }
+    }
+
+    return 0;
+}
+
+
+#ifdef DEBUG
+/**
+ * Symbol debug output.
+ * @param   pSym    Symbol to dump.
+ * @param   pszMsg  Message to put first in the dump.
+ */
+static void         symDbg(PWLDSYM pSym, const char *pszMsg)
+{
+    if (pszMsg)
+        fprintf(stderr, "weakld: dbg: %s:", pszMsg);
+    else
+        fprintf(stderr, "weakld: dbg:");
+    if (pSym)
+    {
+        fprintf(stderr, " '%s'", pSym->pszName);
+        switch (pSym->fFlags & WLDSF_TYPEMASK)
+        {
+            case WLDSF_PUBLIC:  fprintf(stderr, " PUBLIC"); break;
+            case WLDSF_COMM:    fprintf(stderr, " COMM"); break;
+            case WLDSF_IMPORT:  fprintf(stderr, " IMPORT"); break;
+            case WLDSF_UNDEF:   fprintf(stderr, " UNDEF"); break;
+            case WLDSF_WKEXT:   fprintf(stderr, " WKEXT"); break;
+            default:            fprintf(stderr, " !!!internal error!!!"); asm("int $3"); break;
+        }
+        if (pSym->fFlags & WLDSF_WEAK)
+            fprintf(stderr, " WEAK");
+        if (pSym->fFlags & WLDSF_ALIAS)
+            fprintf(stderr, " ALIAS");
+        if (pSym->fFlags & WLDSF_EXPORT)
+            fprintf(stderr, " ALIAS");
+        if (pSym->fFlags & WLDSF_UNCERTAIN)
+            fprintf(stderr, " UNCERTAIN");
+    }
+    else
+        fprintf(stderr, " <Symbol is NULL>");
+    fprintf(stderr, "\n");
+}
+#endif 
 
 
@@ -517,5 +628,5 @@
  *      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)
+ *      4. adding a COMM where a !WEAK COMM exists. 
  *      5. adding a WEAK PUBLIC or WEAK COMM where a PUBLIC or COMM exists.
  *
@@ -550,11 +661,8 @@
  * @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)
+static PWLDSYM      symAdd(PWLD pWld, PWLDMOD pMod, unsigned fFlags, const char *pachName, int cchName, PWLDSYMACTION peAction)
 {
     PWLDSYM     pSym;                   /* The symbol. */
@@ -578,5 +686,5 @@
         {
             cchNameWeak = cchName;
-            cchName = pachName - pach;
+            cchName = pach - pachName;
             fFlags |= WLDSF_WEAK;
             /* If WKEXT we'll upgrade it to weak undefined. (yeah, big deal?) */
@@ -586,5 +694,5 @@
         }
     uHash = hash(pachName, cchName);
-    pszName = (pWld->fFlags & WLDC_CASE_INSENSITIVE ? strpool_addn : strpool_addnu)(pWld->pStrMisc, pachName, cchName);
+    pszName = (pWld->fFlags & WLDC_CASE_INSENSITIVE ? strpool_addnu : strpool_addn)(pWld->pStrMisc, pachName, cchName);
 
     /* search for existing symbol  */
@@ -622,5 +730,5 @@
          *      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)
+         *      4. adding a COMM where a !WEAK COMM exists. 
          *      5. adding a WEAK PUBLIC or WEAK COMM where a PUBLIC or COMM exists.
          */
@@ -702,4 +810,5 @@
             pSym->fFlags = (pSym->fFlags & ~(WLDSF_TYPEMASK | WLDSF_WEAK | WLDSF_UNCERTAIN | WLDSF_LIBSEARCH)) | fFlags;
             if (peAction) *peAction = WLDSA_UP;
+            memset(&pSym->u, 0, sizeof(pSym->u));
         }
         /*
@@ -711,7 +820,7 @@
         else
         {
-            modError(pMod, "Duplicate symbol '%s'.", pszName);
+            modErr(pMod, "Duplicate symbol '%s'.", pszName);
             if (pSym->pMod)
-                modError(pSym->pMod, "Previous symbol defined in this module.");
+                modErr(pSym->pMod, "Previous symbol defined in this module.");
             wldInfo("fFlags new 0x%04x  fFlags old 0x%04x.", fFlags, pSym->fFlags);
             pSym = NULL;
@@ -748,5 +857,5 @@
 
     pSym = symAdd(pWld, pMod, WLDSF_IMPORT | (fLibSearch ? WLDSF_LIBSEARCH : 0),
-                  pachIntName, cchIntName, 0, 0, &eAction);
+                  pachIntName, cchIntName, &eAction);
     if (!pSym)
         return NULL;
@@ -756,6 +865,6 @@
     {
         case WLDSA_NEW:
-            pSym->pszImpMod = pszImpMod;
-            pSym->uImpOrd = uOrdinal;
+            pSym->u.import.pszImpMod = pszImpMod;
+            pSym->u.import.uImpOrd   = uOrdinal;
             break;
 
@@ -764,26 +873,26 @@
             if ((pSym->fFlags & WLDSF_TYPEMASK) == WLDSF_IMPORT)
             {
-                if (!pSym->pszImpMod)
+                if (!pSym->u.import.pszImpMod)
                 {
-                    pSym->pszImpMod = pszImpMod;
-                    pSym->uImpOrd = uOrdinal;
+                    pSym->u.import.pszImpMod = pszImpMod;
+                    pSym->u.import.uImpOrd = uOrdinal;
                 }
                 else
                 {
-                    if (    pSym->pszImpMod != pszImpMod
-                        &&  pSym->uImpOrd != uOrdinal)
+                    if (    pSym->u.import.pszImpMod != pszImpMod
+                        &&  pSym->u.import.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);
+                                pSym->pszName, pSym->u.import.pszImpMod, pszImpMod, pSym->u.import.uImpOrd, uOrdinal);
                     }
-                    else if (pSym->uImpOrd != uOrdinal)
+                    else if (pSym->u.import.uImpOrd != uOrdinal)
                     {
                         modWarn(pMod, "Existing import '%s' have different ordinal (%d != %d).",
-                                pSym->pszName, pSym->uImpOrd, uOrdinal);
+                                pSym->pszName, pSym->u.import.uImpOrd, uOrdinal);
                     }
-                    else if (pSym->pszImpMod != pszImpMod)
+                    else if (pSym->u.import.pszImpMod != pszImpMod)
                     {
                         modWarn(pMod, "Existing import '%s' have different module name than the new ('%s' != '%s').",
-                                pSym->pszName, pSym->pszImpMod, pszImpMod);
+                                pSym->pszName, pSym->u.import.pszImpMod, pszImpMod);
                     }
                 }
@@ -841,5 +950,5 @@
      */
     pSym = symAdd(pWld, pMod, WLDSF_UNDEF | (fLibSearch ? WLDSF_LIBSEARCH : 0),
-                  pachExpName, cchExpName, 0, 0, NULL);
+                  pachExpName, cchExpName, NULL);
     if (!pSym)
         return NULL;
@@ -861,10 +970,10 @@
          */
         pSymAlias = symAdd(pWld, pMod, WLDSF_UNDEF | (fLibSearch ? WLDSF_LIBSEARCH : 0),
-                           pachIntName, cchIntName, 0, 0, NULL);
+                           pachIntName, cchIntName, NULL);
         if (!pSymAlias)
             return NULL;
         if (pSymAlias != pSym && (pSym->fFlags & WLDSF_ALIAS) && pSym->pAliasFor != pSymAlias)
         {
-            modError(pMod, "Can't export an alias!.");
+            modErr(pMod, "Can't export an alias!.");
             pSym = NULL;
         }
@@ -885,4 +994,167 @@
 }
 
+
+/**
+ * Adds a public 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   pachName    Exported name.
+ * @param   cchName     Length of that name. -1 if zero terminated string.
+ * @param   ulValue     Value of the symbol.
+ * @param   iSegment    Segment of pMod in which this symbol is defined.
+ *                      Use -1 if segment is not relevant.
+ */
+static PWLDSYM symAddPublic(PWLD pWld, PWLDMOD pMod, int fLibSearch,
+                            const char *pachName, int cchName,
+                            unsigned long ulValue, int iSegment, int iGroup)
+{
+    PWLDSYM         pSym;
+
+    pSym = symAdd(pWld, pMod, WLDSF_PUBLIC | (fLibSearch ? WLDSF_LIBSEARCH : 0),
+                  pachName, cchName, NULL);
+    if (!pSym)
+        return NULL;
+    /* @todo: handle values ulValue, iSegment and iGroup? Not really required for this job... */
+    return pSym;
+}
+
+
+/**
+ * Adds an undefined 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   pachName    Exported name.
+ * @param   cchName     Length of that name. -1 if zero terminated string.
+ */
+static PWLDSYM symAddUnDef(PWLD pWld, PWLDMOD pMod, int fLibSearch,
+                           const char *pachName, int cchName)
+{
+    PWLDSYM         pSym;
+
+    pSym = symAdd(pWld, pMod, WLDSF_UNDEF | (fLibSearch ? WLDSF_LIBSEARCH : 0),
+                  pachName, cchName, NULL);
+    if (!pSym)
+        return NULL;
+    return pSym;
+}
+
+
+/**
+ * Adds an undefined 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   pachName    Exported name.
+ * @param   cchName     Length of that name. -1 if zero terminated string.
+ */
+static PWLDSYM symAddAlias(PWLD pWld, PWLDMOD pMod, int fLibSearch,
+                           const char *pachAliasName, int cchAliasName,
+                           const char *pachName, int cchName
+                           )
+{
+    WLDSYMACTION    eAction;
+    PWLDSYM         pSym;
+
+    /*
+     * Start by adding the alias it self.
+     */
+    pSym = symAdd(pWld, pMod, WLDSF_PUBLIC | WLDSF_ALIAS | (fLibSearch ? WLDSF_LIBSEARCH : 0),
+                  pachAliasName, cchAliasName, &eAction);
+    if (!pSym)
+        return NULL;
+    switch (eAction)
+    {
+        case WLDSA_NEW:
+        case WLDSA_UP:
+        {
+            if (!pSym->pAliasFor)
+            {
+                PWLDSYM pSym2 = symAdd(pWld, pMod, WLDSF_UNDEF | (fLibSearch ? WLDSF_LIBSEARCH : 0),
+                                       pachName, cchName, NULL);
+                if (!pSym2)
+                    return NULL;
+                pSym->pAliasFor = pSym2;
+            }
+            else
+            {
+                modErr(pMod, "Aliased symbol apparently existed already (upgraded - internal error?).");
+                pSym = NULL;
+            }
+            break;
+        }
+
+        case WLDSA_OLD:
+            modErr(pMod, "Aliased symbol already exists.");
+            pSym = NULL;
+            break;
+        default:
+            WLDINTERR(pWld, pMod);
+    }
+
+    return pSym;
+}
+
+
+/**
+ * Adds(/Marks) an communal 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   fDataType   Datatype.
+ * @param   cElements   Number of elements.
+ * @param   cbElement   Size of one element.
+ * @param   pachName    Symbol name.
+ * @param   cchName     Length of the name. -1 if zero terminated string.
+ */
+static PWLDSYM symAddComdef(PWLD pWld, PWLDMOD pMod, int fLibSearch,
+                            const char *pachName, int cchName,
+                            signed long cElements, signed long cbElement)
+{
+    PWLDSYM         pSym;
+    WLDSYMACTION    eAction;
+
+    /*
+     * Add external name.
+     */
+    pSym = symAdd(pWld, pMod, WLDSF_COMM | (fLibSearch ? WLDSF_LIBSEARCH : 0),
+                  pachName, cchName, NULL);
+    if (!pSym)
+        return NULL;
+    
+    cbElement *= (cElements > 0 ? cElements : 1); /* make it a size */
+    switch (eAction)
+    {
+        case WLDSA_NEW:
+            pSym->u.comm.cb        = cbElement * (cElements > 0 ? cElements : 1);
+            pSym->u.comm.cElements = cElements;
+            break;
+
+        case WLDSA_UP:
+        case WLDSA_OLD:
+            /* merge size */
+            if (pSym->u.comm.cElements < cElements)
+                pSym->u.comm.cElements = cElements;
+            if (pSym->u.comm.cb < cbElement)
+                pSym->u.comm.cb = cbElement;
+            pSym = NULL;
+            break;
+
+        default:
+            WLDINTERR(pWld, pMod);
+    }
+    
+    return pSym;
+}
+
 /**
  * Reads an OMF module from a file.
@@ -908,10 +1180,11 @@
     int             fFirst = 1;         /* First record indicator. */
     /* generic stuff we'll use alot with not status associated. */
-    int             cch;
+    //int             cch;
     PWLDSYM         pSym;
-    PWLDSYM         pSym2;
+    //PWLDSYM         pSym2;
     int             i;
     unsigned long   ul;
-    unsigned short  us;
+    signed long     l, l2, l3;
+    unsigned short  us, us2, us3;
     unsigned char   uch, uch2, uch3;
 
@@ -935,9 +1208,29 @@
             void *              pv;
         } u, u1, u2, u3;
+        
         /** macro for getting a OMF index out of the buffer */
         #define OMF_GETINDEX()  (*u.puch & 0x80 ? ((*u.pch++ & 0x7f) << 8) + *u.pch++ : *u.pch++)
         #define OMF_BYTE()      (*u.puch++)
         #define OMF_WORD()      (*u.pus++)
+        #define OMF_24BITWORD() (OMF_BYTE() | (OMF_WORD() << 8))
+        #define OMF_DWORD()     (*u.pul++)
         #define OMF_MORE()      (u.puch - &achBuffer[0] < (int)OmfRec.cb - 1)
+        #define OMF_IS32BIT()   ((OmfRec.chType & REC32) != 0)
+        #define OMF_GETTYPELEN(l) \
+            do                                                       \
+            {                                                        \
+                l = OMF_BYTE();                                      \
+                if (l > 128)                                         \
+                    switch (l)                                       \
+                    {                                                \
+                        case 0x81: l = OMF_WORD(); break;            \
+                        case 0x84: l = OMF_24BITWORD(); break;       \
+                        case 0x88: l = OMF_DWORD(); break;           \
+                        default:                                     \
+                            modErr(pMod, "Invalid type length!");    \
+                            goto failure;                            \
+                    }                                                \
+            } while (0)
+
 
         u.pv = &achBuffer[0];
@@ -946,5 +1239,5 @@
         if (fread(&OmfRec, sizeof(OmfRec), 1, phFile) != 1)
         {
-            modError(pMod, "read error. (offset ~= %#x).", ftell(phFile));
+            modErr(pMod, "read error. (offset ~= %#x).", ftell(phFile));
             goto failure;
         }
@@ -954,5 +1247,5 @@
             if (OmfRec.chType != THEADR)
             {
-                modError(pMod, "invalid object module (offset %#x).", pMod->off);
+                modErr(pMod, "invalid object module (offset %#x).", pMod->off);
                 goto failure;
             }
@@ -983,5 +1276,5 @@
         if (fread(achBuffer, OmfRec.cb, 1, phFile) != 1)
         {
-            modError(pMod, "read error. (offset ~= %#x)", ftell(phFile));
+            modErr(pMod, "read error. (offset ~= %#x)", ftell(phFile));
             goto failure;
         }
@@ -1010,5 +1303,5 @@
                                 || !papExts[iDefault])
                             {
-                                modError(pMod, "Invalid WKEXT record.");
+                                modErr(pMod, "Invalid WKEXT record.");
                                 goto failure;
                             }
@@ -1017,4 +1310,5 @@
                                 papExts[iWeak]->fFlags = (papExts[iWeak]->fFlags & ~(WLDSF_TYPEMASK | WLDSF_UNCERTAIN)) | WLDSF_WKEXT;
                                 papExts[iWeak]->pWeakDefault = papExts[iDefault];
+                                SYMDBG(papExts[iWeak], "WKEXT");
                             }
                             else if (   (papExts[iWeak]->fFlags & WLDSF_TYPEMASK) == WLDSF_WKEXT
@@ -1046,4 +1340,5 @@
                                                     ul);
                                 if (!pSym) goto failure;
+                                SYMDBG(pSym, "IMPDEF");
                                 break;
                             }
@@ -1069,4 +1364,5 @@
                                                     ul);
                                 if (!pSym) goto failure;
+                                SYMDBG(pSym, "EXPDEF");
                                 break;
                             }
@@ -1076,6 +1372,14 @@
                 break;
 
-            case EXTDEF: case EXTDEF | REC32:
+            case EXTDEF:
             {
+                while (OMF_MORE())
+                {
+                    u1 = u; u.pch += 1 + *u.puch;
+                    ul = OMF_GETINDEX(); /* typeindex */
+                    pSym = symAddUnDef(pWld, pMod, fLibSearch, u1.puch + 1, *u1.puch);
+                    if (!pSym) goto failure;
+                    SYMDBG(pSym, "EXTDEF");
+                }
                 break;
             }
@@ -1083,4 +1387,18 @@
             case PUBDEF: case PUBDEF | REC32:
             {
+                us2 = OMF_GETINDEX();           /* group index */
+                us3 = OMF_GETINDEX();           /* segment index */
+                if (!us3)
+                    us = OMF_WORD();            /* base frame - ignored */
+                while (OMF_MORE())
+                {
+                    u1 = u; u.pch += 1 + *u.puch;   /* public name */
+                    ul = OMF_IS32BIT() ? OMF_DWORD() : OMF_WORD();
+                    us = OMF_GETINDEX();            /* typeindex */
+                    pSym = symAddPublic(pWld, pMod, fLibSearch, u1.puch + 1, *u1.puch, 
+                                        ul, us3, us2);
+                    if (!pSym) goto failure;
+                    SYMDBG(pSym, "PUBDEF");
+                }
                 break;
             }
@@ -1088,4 +1406,14 @@
             case ALIAS: case ALIAS | REC32:
             {
+                while (OMF_MORE())
+                {
+                    u1 = u; u.pch += 1 + *u.puch;   /* alias name */
+                    u2 = u; u.pch += 1 + *u.puch;   /* substitutt name. */
+                    pSym = symAddAlias(pWld, pMod, fLibSearch, 
+                                       u1.puch + 1, *u1.puch, 
+                                       u2.puch + 1, *u2.puch);
+                    if (!pSym) goto failure;
+                    SYMDBG(pSym, "ALIAS");
+                }
                 break;
             }
@@ -1093,4 +1421,30 @@
             case COMDEF: case COMDEF | REC32:
             {
+                while (OMF_MORE())
+                {
+                    u1 = u; u.pch += 1 + *u.puch;   /* communal name (specs say 1-2 length...) */
+                    us2 = OMF_GETINDEX();           /* typeindex */
+                    uch2 = OMF_BYTE();              /* date type */
+                    switch (uch2)
+                    {
+                        case COMDEF_TYPEFAR:
+                            OMF_GETTYPELEN(l2);     /* number of elements */
+                            OMF_GETTYPELEN(l3);     /* element size */
+                            break;
+                        case COMDEF_TYPENEAR:
+                            l2 = 1;                 /* number of elements */  
+                            OMF_GETTYPELEN(l3);     /* element size */        
+                            break;
+                        default:
+                            modErr(pMod, "Invalid COMDEF type %x.", (int)uch2);
+                            goto failure;
+                    }
+
+                    pSym = symAddComdef(pWld, pMod, fLibSearch, 
+                                        u1.puch + 1, *u1.puch, 
+                                        l2, l3);
+                    if (!pSym) goto failure;
+                    SYMDBG(pSym, "ALIAS");
+                }
                 break;
             }
@@ -1102,5 +1456,5 @@
 
             case LIBHDR:
-                modError(pMod, "invalid object module (LIBHDR).");
+                modErr(pMod, "invalid object module (LIBHDR).");
                 goto failure;
             default:
@@ -1111,4 +1465,11 @@
 
         #undef OMF_GETINDEX
+        #undef OMF_BYTE
+        #undef OMF_WORD
+        #undef OMF_24BITWORD
+        #undef OMF_DWORD
+        #undef OMF_MORE
+        #undef OMF_IS32BIT
+        #undef OMF_GETTYPELEN
     }
 
@@ -1341,4 +1702,81 @@
 
 /**
+ * Symbol enumeration callback function of wld_generate_weakobj().
+ * It writes alias for weak symbols.
+ *
+ * @returns 0 on success
+ * @returns !0 on failure after writing sufficient error message.
+ * @param   pWld    Linker instance.
+ * @param   pSym    Symbol.
+ * @param   pvUser  Pointer to a FILE stream.
+ */
+static int weakobjEnum(PWLD pWld, PWLDSYM pSym, void *pvUser)
+{
+    if (pSym->pszWeakName)
+    {
+        int     cch = strlen(pSym->pszWeakName);
+        int     cchAlias = strlen(pSym->pszName);
+        unsigned char uch;
+        OMFREC  hdr;
+
+        WLDINFO(pWld, ("using weak %s for %s", pSym->pszWeakName, pSym->pszName));
+
+        /* paranoia */
+        if (cchAlias > 255)
+        {
+            wldErr(pWld, "Symbol '%s' are too long (%d).", pSym->pszName, cchAlias);
+            return -1;
+        }
+        if (cch > 255)
+        {
+            wldErr(pWld, "Symbol '%s' are too long (%d).", pSym->pszWeakName, cch);
+            return -1;
+        }
+
+        /* write header */
+        hdr.chType = ALIAS;
+        hdr.cb = cchAlias + cch + 3;
+        if (fwrite(&hdr, sizeof(hdr), 1, (FILE*)pvUser) != 1)
+        {
+            wldErr(pWld, "Error occured while writing weak aliases. (1)");
+            return -1;  
+        }
+
+        /* write alias string */
+        uch = cchAlias;
+        if (    fwrite(&uch, sizeof(uch), 1, (FILE*)pvUser) != 1
+            ||  fwrite(pSym->pszName, cchAlias, 1, (FILE*)pvUser) != 1
+                )
+
+        {
+            wldErr(pWld, "Error occured while writing weak aliases (2).");
+            return -1;  
+        }
+
+        /* write substitute string */
+        uch = cch;
+        if (    fwrite(&uch, sizeof(uch), 1, (FILE*)pvUser) != 1
+            ||  fwrite(pSym->pszWeakName, cch, 1, (FILE*)pvUser) != 1
+                )
+
+        {
+            wldErr(pWld, "Error occured while writing weak aliases (3).");
+            return -1;  
+        }
+
+        /* write substitute CRC */
+        uch = 0;
+        if (fwrite(&uch, sizeof(uch), 1, (FILE*)pvUser) != 1)
+
+        {
+            wldErr(pWld, "Error occured while writing weak aliases (4).");
+            return -1;  
+        }
+    }
+    return 0;
+}
+
+
+/**
  * Generates a object file containing alias for resolving the weak
  * symbol references in the linked executable.
@@ -1355,4 +1793,6 @@
 {
     char *      psz;
+    FILE *      phFile;
+    int         rc = -1;
 
     *pszName = '\0';
@@ -1370,7 +1810,67 @@
         fprintf(stderr, "weakld: info: generating weakobj object file '%s'.\n", pszName);
 
-    *pszName = '\0';
-    return 0;
-
-}
-
+    /* open the file */
+    phFile = fopen(pszName, "wr");
+    if (phFile)
+    {
+        #pragma pack(1)
+        struct omfstuff
+        {
+            OMFREC  hdr;
+            char ach[256];
+        } omf;
+        #pragma pack()
+        int     cch;
+        off_t   offAlias;
+
+        /* Write object file header. */
+        cch = strlen("wk.obj");
+        omf.hdr.chType = THEADR;
+        omf.hdr.cb = cch + 2;           /* name + crc */
+        omf.ach[0] = cch;           /* module name */
+        memcpy(&omf.ach[1], "wk.obj", cch);
+        omf.ach[1+cch] = 0;         /* crc */
+        fwrite(&omf, omf.hdr.cb + sizeof(OMFREC), 1, phFile);
+        /* todo: check if we'll need more shit here to satisfy the linkers */
+
+
+        /* Make aliases  */
+        offAlias = ftell(phFile);       /* save this to see if anything is added. */
+        rc = symEnum(pWld, &pWld->Global, 
+                     WLDSF_WEAK, WLDSF_WEAK,
+                     weakobjEnum, phFile);
+        if (rc || ftell(phFile) == offAlias)
+        {
+            if (!rc)
+                WLDINFO(pWld, ("No weak alias needed, deleting file."));
+            fclose(phFile);
+            remove(pszName);
+            *pszName = '\0';
+        }
+        else
+        {
+           /* write end of module */
+           omf.hdr.chType = MODEND;
+           omf.hdr.cb = 2;
+           omf.ach[0] = omf.ach[1] = 0;
+           if (fwrite(&omf, omf.hdr.cb + sizeof(OMFREC), 1, phFile) == 1)
+               fclose(phFile);
+           else
+           {
+               wldErr(pWld, "Failed to write to '%s'.", pszName);
+               rc = -1;
+               fclose(phFile);
+               remove(pszName);
+               *pszName = '\0';
+           }
+        }
+    }
+    else
+    {
+        wldErr(pWld, "Failed to open '%s' for writing.", pszName);
+        *pszName = '\0';
+    }
+
+    return rc;
+}
+
