Index: trunk/src/emx/src/emxomf/emxomf.c
===================================================================
--- trunk/src/emx/src/emxomf/emxomf.c	(revision 59)
+++ trunk/src/emx/src/emxomf/emxomf.c	(revision 60)
@@ -25,4 +25,6 @@
 #include <stdarg.h>
 #include <string.h>
+#include <alloca.h>
+#include <ctype.h>
 #include <getopt.h>
 #include <sys/param.h>
@@ -125,4 +127,15 @@
 };
 
+/* This structure keeps track which weak symbol and where it is defined,
+   to simulate weak symbols in OMF (which aren't supported in OMF) */
+
+struct weaksym
+{
+  struct weaksym *next;		/* Next weak symbol in chain */
+  char *name;			/* Symbol name */
+  char *module;			/* Object file where it should be defined */
+  int used;			/* 1 if the symbol has been encountered */
+};
+
 
 /* The number of symbols in the a.out file. */
@@ -237,4 +250,10 @@
 static int opt_x = FALSE;
 
+/* Suppress reading and/or writing of the weaksyms.omf file */
+static int opt_w = FALSE;
+
+/* Remove underscores from all symbol names */
+static int opt_rmunder = FALSE;
+
 /* This is the page size for OMF libraries.  It is set by the -p
    option. */
@@ -258,4 +277,14 @@
 /* The index of the "WEAK$ZERO" symbol or 0. */
 static int weak_zero_index;
+
+/* The list of currently known OMF symbols */
+static struct weaksym *weak_symbol_list;
+static struct weaksym **weak_symbol_top = &weak_symbol_list;
+
+/* 1 whenever the weak symbol list has been altered */
+static int weak_list_altered;
+
+/* The file name of the weak symbol list file */
+static char *weak_list_filename;
 
 /* OMF name indices: segments, classes, groups, etc. */
@@ -348,5 +377,5 @@
 /* The name of the identifier manipulation DLL.  If this variable is
    NULL, no IDMDLL record is written. */
-static char *idmdll_name = "GPPDEMID";
+static char *idmdll_name = "GPP3DEM";
 
 /* If this variable is TRUE (-b option), we always use the 32-bit
@@ -499,4 +528,14 @@
 
 
+/* Check if we should remove the leading underscore from a symbol name */
+static inline int strip_underscore (const char *name)
+{
+  if (!opt_rmunder)
+    return 0;
+
+  return (*name == '_');
+}
+
+
 /* Find an a.out symbol.  The underscore character `_' is prepended to
    NAME.  On success, a pointer to the symbol table entry (in the
@@ -506,5 +545,5 @@
 const struct nlist *find_symbol (const char *name)
 {
-  int i, j, n, len, ok, t;
+  int i, j, n, len, t;
   const byte *s;
   
@@ -515,10 +554,9 @@
   while (i < str_size)
     {
-      ok = TRUE; s = name;
-      if (str_ptr[i] == '_')
+      int sym_ofs = i;
+      s = name;
+      if (strip_underscore (str_ptr + i))
         ++i;
-      else
-        ok = FALSE;
-      if (ok && memcmp (name, str_ptr+i, len+1) == 0)
+      if (memcmp (name, str_ptr+i, len+1) == 0)
 	{
 
@@ -527,7 +565,6 @@
 
 	  n = sym_count;
-          --i;                  /* Move back to the underscore */
 	  for (j = 0; j < n; ++j)
-	    if (sym_ptr[j].string == i)
+	    if (sym_ptr[j].string == sym_ofs)
 	      {
 		t = sym_ptr[j].type & ~N_EXT;
@@ -540,4 +577,132 @@
     }
   return NULL;                  /* Symbol not found */
+}
+
+
+/* Add a symbol to weak symbol list */
+
+static struct weaksym *add_weak (const char *symname, const char *modname)
+{
+  struct weaksym *newsym = malloc (sizeof (struct weaksym));
+  newsym->name = xstrdup (symname);
+  newsym->module = xstrdup (modname);
+  newsym->used = 0;
+  newsym->next = NULL;
+  *weak_symbol_top = newsym;
+  weak_symbol_top = &newsym->next;
+  weak_list_altered = 1;
+  return newsym;
+}
+
+
+/* Load the weak symbols table from the weaksyms.omf file.
+ * We emulate the weak symbol functionality in the following way:
+ * first time we encounter a weak symbol, we mark it as "strong"
+ * and remember the first object file where it was encountered.
+ * Then when another instance of this weak symbol is encountered
+ * the output file name is checked; if it is a different object file,
+ * the symbol is marked as local. Otherwise it is marked as strong.
+ * Finally, when we find any external references to this symbol, they
+ * are marked as "OMF weak reference", e.g. the N_WEAKU type
+ * (which is quite different from a.out weaks, thats why we have
+ * to dig all that mess!). Alas, this mechanism can require multi-pass
+ * builds for complex cases...
+ */
+
+static void weak_load (void)
+{
+  FILE *wf;
+
+  if (opt_w)
+    return;
+
+  /* Find and open the weak symbol list file */
+  weak_list_filename = getenv ("GCC_WEAKSYMS");
+  if (!weak_list_filename)
+    weak_list_filename = "weaksyms.omf";
+  wf = fopen (weak_list_filename, "r");
+  if (!wf)
+    return;
+
+  /* Every line of the file contains something like:
+       __symbol:object_file
+     or just
+       __symbol
+  */
+
+  char line [1024];
+  while (fgets (line, sizeof (line), wf))
+    {
+      char *eol = strchr (line, 0);
+      while ((eol > line) && (isspace (eol [-1])))
+        eol--;
+      *eol = 0;
+      char *sep = strchr (line, ':');
+      if (!sep)
+        {
+          fprintf (stderr, "WARNING: bad line `%s' in weak symbol list file `%s'\n",
+            line, weak_list_filename);
+          continue;
+        }
+
+      *sep = 0;
+      add_weak (line, sep + 1);
+    }
+
+  fclose (wf);
+
+  /* Mark the list as unmodified */
+  weak_list_altered = 0;
+}
+
+
+/* Save the weak symbol list */
+
+static void weak_save (void)
+{
+  FILE *wf;
+  struct weaksym *wsym;
+
+  if (opt_w)
+    return;
+
+  /* Find and open the weak symbol list file */
+  wf = fopen (weak_list_filename, "w");
+  if (!wf)
+    return;
+
+  for (wsym = weak_symbol_list; wsym; wsym = wsym->next)
+    fprintf (wf, "%s:%s\n", wsym->name, wsym->module);
+
+  fclose (wf);
+}
+
+
+/* Free the weak symbol list */
+
+static void weak_free (void)
+{
+  struct weaksym *cur = weak_symbol_list;
+  while (cur)
+    {
+      struct weaksym *next = cur->next;
+      free (cur->name);
+      free (cur->module);
+      free (cur);
+      cur = next;
+    }
+  weak_symbol_list = NULL;
+}
+
+
+/* Find if a symbol is weak */
+
+static struct weaksym *is_weak (const char *symname)
+{
+  struct weaksym *wsym;
+  for (wsym = weak_symbol_list; wsym; wsym = wsym->next)
+    if (!strcmp (symname, wsym->name))
+      return wsym;
+  return NULL;
 }
 
@@ -742,5 +907,5 @@
 static void put_sym (const char *src)
 {
-  if (*src == '_')
+  if (strip_underscore (src))
     ++src;
   put_str (src);
@@ -965,4 +1130,55 @@
 
 
+/* Check all external symbol references for weakness; if a symbol is weak,
+   mark it as N_WEAKU so that it is later writen within a WKEXT record.
+   Also we convert a.out-style weak symbols here as normal public symbols,
+   as the sense of weak is reverse in OMF */
+
+static void weak_process (void)
+{
+  int i;
+
+#define SETTYPE(t) ((struct nlist *)sym_ptr)[i].type = t
+
+  for (i = 0; i < sym_count; ++i)
+    if ((sym_ptr[i].type >= N_WEAKA) && (sym_ptr[i].type <= N_WEAKB))
+      {
+        const char *name = str_ptr + sym_ptr[i].string;
+
+        int public = N_EXT;
+
+        /* Add the symbol to weak list if not already */
+        struct weaksym *wsym = is_weak (name);
+        if (!wsym)
+          wsym = add_weak (name, out_fname);
+        else if (strcmp (out_fname, wsym->module) || wsym->used)
+          public = 0;
+        /* If the symbol is exported more than once (e.g. from an archive),
+           export just the first instance... */
+        wsym->used = 1;
+
+        /* Now convert it to a normal public symbol */
+        switch (sym_ptr[i].type)
+          {
+            case N_WEAKA: SETTYPE (N_ABS  | public); break;
+            case N_WEAKT: SETTYPE (N_TEXT | public); break;
+            case N_WEAKD: SETTYPE (N_DATA | public); break;
+            case N_WEAKB: SETTYPE (N_BSS  | public); break;
+          }
+      }
+    else if ((sym_ptr[i].type & N_EXT) && is_weak (str_ptr + sym_ptr[i].string))
+      {
+         /* Convert a external reference to N_WEAKU */
+         /* P.S. As experiments show, WKEXT works somewhat strangely
+            with LINK386 (sometimes such external references are left
+            unresolved, even that they could be resolved), thus the
+            following line is commented out */
+         /*SETTYPE (N_WEAKU);*/
+      }
+
+#undef SETTYPE
+}
+
+
 /* Write ALIAS records into the output file for all indirect
    references. */
@@ -984,5 +1200,5 @@
           {
             pub_name = str_ptr + sym_ptr[i].string;
-            if (*pub_name == '_')
+            if (strip_underscore (pub_name))
               ++pub_name;
             if (omflib_add_pub (out_lib, pub_name, mod_page, lib_errmsg) != 0)
@@ -1034,5 +1250,5 @@
                   {
                     pub_name = name;
-                    if (*pub_name == '_')
+                    if (strip_underscore (pub_name))
                       ++pub_name;
                     if (omflib_add_pub (out_lib, pub_name, mod_page,
@@ -1076,4 +1292,6 @@
   write_pubdef1 (N_DATA, udat_index, FALSE, text_size);
   write_pubdef1 (N_DATA, udat_index, TRUE, text_size);
+  write_pubdef1 (N_BSS, bss_index, FALSE, text_size + data_size);
+  write_pubdef1 (N_BSS, bss_index, TRUE, text_size + data_size);
 }
 
@@ -1171,5 +1389,6 @@
     The segment attributes byte contains the following fields:
 
-    A (bits 5-7)        Alignment (101=relocatable, 32-bit alignment)
+    A (bits 5-7)        Alignment (011=relocatable, paragraph (16b) alignment)
+                        (before gcc 3.2.2: 101=relocatable, 32-bit alignment)
     C (bits 2-4)        Combination (010=PUBLIC, 101=STACK)
     B (bit 1)           Big (segment length is 64KB)
@@ -1180,5 +1399,5 @@
   byte seg_attr;
 
-  seg_attr = (stack ? 0xb5 : 0xa9);
+  seg_attr = (stack ? 0x75 : 0x69);
   if (size > 0x10000 || force_big)
     {
@@ -2135,5 +2354,5 @@
   /* Skip a leading underscore character if present. */
 
-  if (*pub_name == '_')
+  if (strip_underscore (pub_name))
     ++pub_name;
 
@@ -2629,4 +2848,8 @@
                     case N_INDR|N_EXT:
                     case N_WEAKU:
+                    case N_WEAKA:
+                    case N_WEAKT:
+                    case N_WEAKD:
+                    case N_WEAKB:
       case N_SETA:  case N_SETA|N_EXT:
       case N_SETT:  case N_SETT|N_EXT:
@@ -2847,4 +3070,7 @@
   if (do_set_groups)
     write_set_groups ();
+
+  /* Process weak symbols */
+  weak_process ();
 
   /* Define external, communal and public symbols (EXTDEF, WKEXT,
@@ -2946,4 +3172,6 @@
   puts ("  -I <idmdll>        Name the identifier manipulation DLL");
   puts ("  -O <directory>     Extract files to <directory>");
+  puts ("  -w                 Suppress reading/writing of the weaksyms.omf file");
+  puts ("  -z                 Remove underscores from all symbol names");
   exit (1);
 }
@@ -3331,5 +3559,5 @@
   /* Parse the command line options. */
 
-  while ((c = getopt (argc, argv, "bdD:gi:I:m:l::o:p:qO:r:R:sux")) != EOF)
+  while ((c = getopt (argc, argv, "bdD:gi:I:m:l::o:p:qO:r:R:suxwz")) != EOF)
     switch (c)
       {
@@ -3408,4 +3636,10 @@
         opt_x = TRUE;
         break;
+      case 'w':
+        opt_w = TRUE;
+        break;
+      case 'z':
+        opt_rmunder = TRUE;
+        break;
       default:
         usage ();
@@ -3417,7 +3651,11 @@
     usage ();
 
+  /* Initialize weak symbol list */
+
+  weak_symbol_list = NULL;
+  weak_load ();
+
   if (opt_o != NULL)
     {
-
       /* If the -o option is used, there must be exactly one input
          file name. */
@@ -3449,4 +3687,13 @@
     }
 
+  /* If the weak symbol list has been altered, save it */
+
+  if (weak_list_altered)
+    weak_save ();
+
+  /* Free the weak symbol list */
+
+  weak_free ();
+
   /* If a LIB response file has been created, finish and close it. */
 
Index: trunk/src/emx/src/emxomf/emxomfld.c
===================================================================
--- trunk/src/emx/src/emxomf/emxomfld.c	(revision 59)
+++ trunk/src/emx/src/emxomf/emxomfld.c	(revision 60)
@@ -28,7 +28,9 @@
 #include <sys/types.h>
 #include <sys/stat.h>
-#include <getopt.h>
+#include <emx/getopt.h>
 #include <errno.h>
+#include <sys/utime.h>
 #include <sys/moddef.h>
+#include <alloca.h>
 #include "defs.h"
 
@@ -142,4 +144,7 @@
 int main (int argc, char *argv[]);
 
+/* To avoid including os2.h... */
+unsigned DosCopy (char *, char *, unsigned);
+
 
 /* Tell the user how to run this program. */
@@ -461,4 +466,9 @@
   const char *ext;
   char tmp[512], *t;
+  static char emxshell [200];
+
+  /* Drop EMXSHELL since it can point to a Unix shell which is bad for us */
+  sprintf (emxshell, "EMXSHELL=%s", getenv ("OS2_SHELL"));
+  putenv (emxshell);
 
   /* Close and delete the response file on exit. */
@@ -675,8 +685,21 @@
                         statement is used for a segment of class
                         'CODE').  Not grouping neighboring code
-                        segments would break sets */
+                        segments would break sets
+
+     For ILINK the following option is passed:
+
+     /NOFR[EEFORMAT]    Use /NOFREEFORMAT to allow a LINK386-compatible
+                        command line syntax, in which different types of file
+                        are grouped and separated by commas.
+  */
 
   put_arg (linker_name, TRUE);
+
+  /* If the linker is ILINK, don't use the /BAT{CH} option */
+  t = _getname (linker_name);
+  if (strnicmp (t, "ILINK", 5))
   put_arg ("/bat", FALSE);
+  else
+    put_arg ("/nofree", FALSE);
   put_arg ("/nol", FALSE);
   put_arg ("/noe", FALSE);
@@ -772,4 +795,7 @@
 
   rc = system (command_line);
+  /* ILINK returns 4 on warnings: consider this as success */
+  if (rc == 4) rc = 0;
+
   if (rc < 0)
     {
@@ -784,5 +810,5 @@
     {
       arg_init (TRUE);
-      put_arg ("rc", TRUE);
+      put_arg ("rc -n", TRUE);
       put_arg (res_fname, TRUE);
       put_arg (output_fname, TRUE);
@@ -802,14 +828,20 @@
   if (rc == 0 && exe_flag)
     {
-      int h;
-
-      h = open (output_fname,
-                O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666);
-      if (h < 0)
+      char execname[512];
+
+      t = xstrdup (output_fname);
+      _remext (t);
+
+      _execname((char *)&execname, sizeof(execname));
+      strcpy(_getname((char *)&execname), "ldstub.bin");
+      /* Copy stub into file */
+      DosCopy((char *)&execname, t, 4);
+      /* Now touch it */
+      if (utime(t, NULL))
         {
           perror ("emxomfld");
           exit (2);
         }
-      close (h);
+      free (t);
     }
 
Index: trunk/src/emx/src/emxomf/stabshll.c
===================================================================
--- trunk/src/emx/src/emxomf/stabshll.c	(revision 59)
+++ trunk/src/emx/src/emxomf/stabshll.c	(revision 60)
@@ -25,4 +25,5 @@
 #include <string.h>
 #include <time.h>
+#include <alloca.h>
 #include "defs.h"
 #include "emxomf.h"
@@ -341,4 +342,12 @@
 static int unnamed_struct_number;
 
+/* Suppress several kinds of warnings since newer gccs generates lots of
+   warnings... */
+
+static void no_warning (char *format, ...)
+{
+  (void)format;
+}
+
 
 /* Start a type table record of type TYPE, with type qualifier QUAL.
@@ -912,5 +921,5 @@
       /* This should not happen. */
 
-      warning ("stabs type %d not defined", tp->d.stabs_ref);
+      no_warning ("stabs type %d not defined", tp->d.stabs_ref);
       return 4;
 
@@ -934,5 +943,5 @@
       if (tp->d.struc.flags & STRUC_FORWARD)
         {
-          warning ("size of incomplete structure %s is unknown",
+          no_warning ("size of incomplete structure %s is unknown",
                    tp->d.struc.name);
           return 0;
@@ -1175,5 +1184,5 @@
   if (*parse_ptr != c)
     {
-      warning ("Invalid symbol data: `%c' expected", c);
+      no_warning ("Invalid symbol data: `%c' expected", c);
       return FALSE;
     }
@@ -1224,5 +1233,5 @@
     default:
       ++parse_ptr;
-      warning ("Invalid visibility: %c", *parse_ptr);
+      no_warning ("Invalid visibility: %c", *parse_ptr);
       if (*parse_ptr != 0)
         ++parse_ptr;
@@ -1361,5 +1370,5 @@
       else
         {
-          warning ("Unknown range type: %lld..%lld", range_lo, range_hi);
+          no_warning ("Unknown range type: %lld..%lld", range_lo, range_hi);
           goto syntax;
         }
@@ -1618,5 +1627,5 @@
                   if (*parse_ptr != ':')
                     {
-                      warning ("Arguments for member function missing");
+                      no_warning ("Arguments for member function missing");
                       goto syntax;
                     }
@@ -1643,5 +1652,5 @@
                       break;
                     default:
-                      warning ("Unknown member function qualifier: %c",
+                      no_warning ("Unknown member function qualifier: %c",
                                *parse_ptr);
                       if (*parse_ptr != 0)
@@ -1673,5 +1682,5 @@
                       break;
                     default:
-                      warning ("Unknown member function qualifier: %c",
+                      no_warning ("Unknown member function qualifier: %c",
                                *parse_ptr);
                       if (*parse_ptr != 0)
@@ -1979,5 +1988,5 @@
 
     default:
-      warning ("Unknown type: %c", *parse_ptr);
+      no_warning ("Unknown type: %c", *parse_ptr);
       goto syntax;
     }
@@ -2008,5 +2017,5 @@
   tp = parse_type (type_name);
   if (*parse_ptr != 0)
-    warning ("unexpected character at end of stabs type: %c", *parse_ptr);
+    no_warning ("unexpected character at end of stabs type: %c", *parse_ptr);
   return tp;
 }
@@ -2032,5 +2041,5 @@
   if (tp->index == -2)
     {
-      warning ("Cycle detected by make_type");
+      no_warning ("Cycle detected by make_type");
       RETURN (0);
     }
@@ -2044,5 +2053,5 @@
       if (t1 == NULL)
         {
-          warning ("Undefined stabs type %d referenced", tp->d.stabs_ref);
+          no_warning ("Undefined stabs type %d referenced", tp->d.stabs_ref);
           RETURN (0x82);        /* 32 bit signed */
         }
@@ -2724,5 +2733,5 @@
           if (sym2 == NULL)
             {
-              warning ("Cannot find address of global variable %s", name);
+              no_warning ("Cannot find address of global variable %s", name);
               return;
             }
