gdb: add target_ops::supports_displaced_step
[deliverable/binutils-gdb.git] / ld / deffilep.y
index 80efb789f02afbaa9a72658ffd8c8d48f30a8d59..51cb1d7fcde6d38160a9b8698b4324153fa50869 100644 (file)
@@ -1,13 +1,12 @@
 %{ /* deffilep.y - parser for .def files */
 
-/*   Copyright 1995, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2005, 2007
-     Free Software Foundation, Inc.
+/*   Copyright (C) 1995-2020 Free Software Foundation, Inc.
 
      This file is part of GNU Binutils.
 
      This program is free software; you can redistribute it and/or modify
      it under the terms of the GNU General Public License as published by
-     the Free Software Foundation; either version 2 of the License, or
+     the Free Software Foundation; either version 3 of the License, or
      (at your option) any later version.
 
      This program is distributed in the hope that it will be useful,
 
      You should have received a copy of the GNU General Public License
      along with this program; if not, write to the Free Software
-     Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
+     Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+     MA 02110-1301, USA.  */
 
 #include "sysdep.h"
 #include "libiberty.h"
 #include "safe-ctype.h"
 #include "bfd.h"
+#include "bfdlink.h"
 #include "ld.h"
 #include "ldmisc.h"
 #include "deffile.h"
 #define        yylval  def_lval
 #define        yychar  def_char
 #define        yydebug def_debug
-#define        yypact  def_pact        
-#define        yyr1    def_r1                  
-#define        yyr2    def_r2                  
-#define        yydef   def_def         
-#define        yychk   def_chk         
-#define        yypgo   def_pgo         
-#define        yyact   def_act         
+#define        yypact  def_pact
+#define        yyr1    def_r1
+#define        yyr2    def_r2
+#define        yydef   def_def
+#define        yychk   def_chk
+#define        yypgo   def_pgo
+#define        yyact   def_act
 #define        yyexca  def_exca
 #define yyerrflag def_errflag
 #define yynerrs        def_nerrs
 #define yytable         def_yytable
 #define yycheck         def_yycheck
 
+typedef struct def_pool_str {
+  struct def_pool_str *next;
+  char data[1];
+} def_pool_str;
+
+static def_pool_str *pool_strs = NULL;
+
+static char *def_pool_alloc (size_t sz);
+static char *def_pool_strdup (const char *str);
+static void def_pool_free (void);
+
 static void def_description (const char *);
-static void def_exports (const char *, const char *, int, int);
+static void def_exports (const char *, const char *, int, int, const char *);
 static void def_heapsize (int, int);
 static void def_import (const char *, const char *, const char *, const char *,
-                       int);
-static void def_image_name (const char *, int, int);
+                       int, const char *);
+static void def_image_name (const char *, bfd_vma, int);
 static void def_section (const char *, int);
 static void def_section_alt (const char *, const char *);
 static void def_stacksize (int, int);
 static void def_version (int, int);
 static void def_directive (char *);
+static void def_aligncomm (char *str, int align);
 static int def_parse (void);
 static int def_error (const char *);
 static int def_lex (void);
@@ -100,18 +113,26 @@ static const char *lex_parse_string_end = 0;
 
 %union {
   char *id;
+  const char *id_const;
   int number;
+  bfd_vma vma;
+  char *digits;
 };
 
-%token NAME LIBRARY DESCRIPTION STACKSIZE HEAPSIZE CODE DATAU DATAL
+%token NAME LIBRARY DESCRIPTION STACKSIZE_K HEAPSIZE CODE DATAU DATAL
 %token SECTIONS EXPORTS IMPORTS VERSIONK BASE CONSTANTU CONSTANTL
-%token PRIVATEU PRIVATEL
-%token READ WRITE EXECUTE SHARED NONAMEU NONAMEL DIRECTIVE
+%token PRIVATEU PRIVATEL ALIGNCOMM
+%token READ WRITE EXECUTE SHARED NONAMEU NONAMEL DIRECTIVE EQUAL
 %token <id> ID
-%token <number> NUMBER
-%type  <number> opt_base opt_ordinal
+%token <digits> DIGITS
+%type  <number> NUMBER
+%type  <vma> VMA opt_base
+%type  <digits> opt_digits
+%type  <number> opt_ordinal
 %type  <number> attr attr_list opt_number exp_opt_list exp_opt
-%type  <id> opt_name opt_equal_name dot_name 
+%type  <id> opt_name opt_name2 opt_equal_name anylang_id opt_id
+%type  <id> opt_equalequal_name
+%type  <id_const> keyword_as_name
 
 %%
 
@@ -119,20 +140,21 @@ start: start command
        | command
        ;
 
-command: 
+command:
                NAME opt_name opt_base { def_image_name ($2, $3, 0); }
        |       LIBRARY opt_name opt_base { def_image_name ($2, $3, 1); }
        |       DESCRIPTION ID { def_description ($2);}
-       |       STACKSIZE NUMBER opt_number { def_stacksize ($2, $3);}
+       |       STACKSIZE_K NUMBER opt_number { def_stacksize ($2, $3);}
        |       HEAPSIZE NUMBER opt_number { def_heapsize ($2, $3);}
        |       CODE attr_list { def_section ("CODE", $2);}
        |       DATAU attr_list  { def_section ("DATA", $2);}
        |       SECTIONS seclist
-       |       EXPORTS explist 
+       |       EXPORTS explist
        |       IMPORTS implist
        |       VERSIONK NUMBER { def_version ($2, 0);}
        |       VERSIONK NUMBER '.' NUMBER { def_version ($2, $4);}
        |       DIRECTIVE ID { def_directive ($2);}
+       |       ALIGNCOMM anylang_id ',' NUMBER { def_aligncomm ($2, $4);}
        ;
 
 
@@ -146,8 +168,8 @@ expline:
                /* The opt_comma is necessary to support both the usual
                  DEF file syntax as well as .drectve syntax which
                  mandates <expsym>,<expoptlist>.  */
-               dot_name opt_equal_name opt_ordinal opt_comma exp_opt_list
-                       { def_exports ($1, $2, $3, $5); }
+               opt_name2 opt_equal_name opt_ordinal opt_comma exp_opt_list opt_comma opt_equalequal_name
+                       { def_exports ($1, $2, $3, $5, $7); }
        ;
 exp_opt_list:
                /* The opt_comma is necessary to support both the usual
@@ -166,18 +188,24 @@ exp_opt:
        |       PRIVATEU        { $$ = 8; }
        |       PRIVATEL        { $$ = 8; }
        ;
-implist:       
+implist:
                implist impline
        |       impline
        ;
 
 impline:
-               ID '=' ID '.' ID '.' ID     { def_import ($1, $3, $5, $7, -1); }
-       |       ID '=' ID '.' ID '.' NUMBER { def_import ($1, $3, $5,  0, $7); }
-       |       ID '=' ID '.' ID            { def_import ($1, $3,  0, $5, -1); }
-       |       ID '=' ID '.' NUMBER        { def_import ($1, $3,  0,  0, $5); }
-       |       ID '.' ID '.' ID            { def_import ( 0, $1, $3, $5, -1); }
-       |       ID '.' ID                   { def_import ( 0, $1,  0, $3, -1); }
+              ID '=' ID '.' ID '.' ID opt_equalequal_name
+                { def_import ($1, $3, $5, $7, -1, $8); }
+       |       ID '=' ID '.' ID '.' NUMBER opt_equalequal_name
+                                { def_import ($1, $3, $5,  0, $7, $8); }
+       |       ID '=' ID '.' ID opt_equalequal_name
+                { def_import ($1, $3,  0, $5, -1, $6); }
+       |       ID '=' ID '.' NUMBER opt_equalequal_name
+                { def_import ($1, $3,  0,  0, $5, $6); }
+       |       ID '.' ID '.' ID opt_equalequal_name
+                { def_import( 0, $1, $3, $5, -1, $6); }
+       |       ID '.' ID opt_equalequal_name
+                { def_import ( 0, $1,  0, $3, -1, $4); }
 ;
 
 seclist:
@@ -197,52 +225,125 @@ attr_list:
 
 opt_comma:
        ','
-       | 
+       |
        ;
 opt_number: ',' NUMBER { $$=$2;}
        |          { $$=-1;}
        ;
-       
+
 attr:
                READ    { $$ = 1;}
-       |       WRITE   { $$ = 2;}      
+       |       WRITE   { $$ = 2;}
        |       EXECUTE { $$=4;}
        |       SHARED  { $$=8;}
        ;
 
-opt_name: ID           { $$ = $1; }
-       | ID '.' ID     
-         { 
-           char *name = xmalloc (strlen ($1) + 1 + strlen ($3) + 1);
+
+keyword_as_name: BASE { $$ = "BASE"; }
+        | CODE { $$ = "CODE"; }
+        | CONSTANTU { $$ = "CONSTANT"; }
+        | CONSTANTL { $$ = "constant"; }
+        | DATAU { $$ = "DATA"; }
+        | DATAL { $$ = "data"; }
+        | DESCRIPTION { $$ = "DESCRIPTION"; }
+        | DIRECTIVE { $$ = "DIRECTIVE"; }
+        | EXECUTE { $$ = "EXECUTE"; }
+        | EXPORTS { $$ = "EXPORTS"; }
+        | HEAPSIZE { $$ = "HEAPSIZE"; }
+        | IMPORTS { $$ = "IMPORTS"; }
+/* Disable LIBRARY keyword as valid symbol-name.  This is necessary
+   for libtool, which places this command after EXPORTS command.
+   This behavior is illegal by specification, but sadly required by
+   by compatibility reasons.
+   See PR binutils/13710
+        | LIBRARY { $$ = "LIBRARY"; } */
+        | NAME { $$ = "NAME"; }
+        | NONAMEU { $$ = "NONAME"; }
+        | NONAMEL { $$ = "noname"; }
+        | PRIVATEU { $$ = "PRIVATE"; }
+        | PRIVATEL { $$ = "private"; }
+        | READ { $$ = "READ"; }
+        | SHARED  { $$ = "SHARED"; }
+        | STACKSIZE_K { $$ = "STACKSIZE"; }
+        | VERSIONK { $$ = "VERSION"; }
+        | WRITE { $$ = "WRITE"; }
+        ;
+
+opt_name2: ID { $$ = $1; }
+       | '.' keyword_as_name
+         {
+           char *name = xmalloc (strlen ($2) + 2);
+           sprintf (name, ".%s", $2);
+           $$ = name;
+         }
+       | '.' opt_name2
+         {
+           char *name = def_pool_alloc (strlen ($2) + 2);
+           sprintf (name, ".%s", $2);
+           $$ = name;
+         }
+       | keyword_as_name '.' opt_name2
+         {
+           char *name = def_pool_alloc (strlen ($1) + 1 + strlen ($3) + 1);
+           sprintf (name, "%s.%s", $1, $3);
+           $$ = name;
+         }
+       | ID '.' opt_name2
+         {
+           char *name = def_pool_alloc (strlen ($1) + 1 + strlen ($3) + 1);
            sprintf (name, "%s.%s", $1, $3);
            $$ = name;
          }
+       ;
+
+opt_name: opt_name2 { $$ = $1; }
        |               { $$ = ""; }
        ;
 
-opt_ordinal: 
+opt_equalequal_name: EQUAL ID  { $$ = $2; }
+       |                                                       { $$ = 0; }
+       ;
+
+opt_ordinal:
          '@' NUMBER     { $$ = $2;}
        |                { $$ = -1;}
        ;
 
 opt_equal_name:
-          '=' dot_name { $$ = $2; }
-        |              { $$ =  0; }                     
+         '=' opt_name2 { $$ = $2; }
+       |               { $$ =  0; }
        ;
 
-opt_base: BASE '=' NUMBER      { $$ = $3;}
-       |       { $$ = -1;}
+opt_base: BASE '=' VMA { $$ = $3;}
+       |       { $$ = (bfd_vma) -1;}
        ;
 
-dot_name: ID           { $$ = $1; }
-       | dot_name '.' ID       
-         { 
-           char *name = xmalloc (strlen ($1) + 1 + strlen ($3) + 1);
-           sprintf (name, "%s.%s", $1, $3);
-           $$ = name;
+anylang_id: ID         { $$ = $1; }
+       | '.' ID
+         {
+           char *id = def_pool_alloc (strlen ($2) + 2);
+           sprintf (id, ".%s", $2);
+           $$ = id;
          }
+       | anylang_id '.' opt_digits opt_id
+         {
+           char *id = def_pool_alloc (strlen ($1) + 1 + strlen ($3) + strlen ($4) + 1);
+           sprintf (id, "%s.%s%s", $1, $3, $4);
+           $$ = id;
+         }
+       ;
+
+opt_digits: DIGITS     { $$ = $1; }
+       |               { $$ = ""; }
+       ;
+
+opt_id: ID             { $$ = $1; }
+       |               { $$ = ""; }
+       ;
+
+NUMBER: DIGITS         { $$ = strtoul ($1, 0, 0); }
        ;
-       
+VMA: DIGITS            { $$ = (bfd_vma) strtoull ($1, 0, 0); }
 
 %%
 
@@ -305,205 +406,316 @@ def_file_parse (const char *filename, def_file *add_to)
     {
       def_file_free (def);
       fclose (the_file);
+      def_pool_free ();
       return 0;
     }
 
   fclose (the_file);
 
-  for (d = directives; d; d = d->next)
+  while ((d = directives) != NULL)
     {
 #if TRACE
       printf ("Adding directive %08x `%s'\n", d->name, d->name);
 #endif
       def_file_add_directive (def, d->name, d->len);
+      directives = d->next;
+      free (d->name);
+      free (d);
     }
+  def_pool_free ();
 
   return def;
 }
 
 void
-def_file_free (def_file *def)
+def_file_free (def_file *fdef)
 {
   int i;
 
-  if (!def)
+  if (!fdef)
     return;
-  if (def->name)
-    free (def->name);
-  if (def->description)
-    free (def->description);
+  free (fdef->name);
+  free (fdef->description);
 
-  if (def->section_defs)
+  if (fdef->section_defs)
     {
-      for (i = 0; i < def->num_section_defs; i++)
+      for (i = 0; i < fdef->num_section_defs; i++)
        {
-         if (def->section_defs[i].name)
-           free (def->section_defs[i].name);
-         if (def->section_defs[i].class)
-           free (def->section_defs[i].class);
+         free (fdef->section_defs[i].name);
+         free (fdef->section_defs[i].class);
        }
-      free (def->section_defs);
+      free (fdef->section_defs);
     }
 
-  if (def->exports)
+  if (fdef->exports)
     {
-      for (i = 0; i < def->num_exports; i++)
+      for (i = 0; i < fdef->num_exports; i++)
        {
-         if (def->exports[i].internal_name
-             && def->exports[i].internal_name != def->exports[i].name)
-           free (def->exports[i].internal_name);
-         if (def->exports[i].name)
-           free (def->exports[i].name);
+         if (fdef->exports[i].internal_name != fdef->exports[i].name)
+           free (fdef->exports[i].internal_name);
+         free (fdef->exports[i].name);
+         free (fdef->exports[i].its_name);
        }
-      free (def->exports);
+      free (fdef->exports);
     }
 
-  if (def->imports)
+  if (fdef->imports)
     {
-      for (i = 0; i < def->num_imports; i++)
+      for (i = 0; i < fdef->num_imports; i++)
        {
-         if (def->imports[i].internal_name
-             && def->imports[i].internal_name != def->imports[i].name)
-           free (def->imports[i].internal_name);
-         if (def->imports[i].name)
-           free (def->imports[i].name);
+         if (fdef->imports[i].internal_name != fdef->imports[i].name)
+           free (fdef->imports[i].internal_name);
+         free (fdef->imports[i].name);
+         free (fdef->imports[i].its_name);
        }
-      free (def->imports);
+      free (fdef->imports);
     }
 
-  while (def->modules)
+  while (fdef->modules)
     {
-      def_file_module *m = def->modules;
-      def->modules = def->modules->next;
+      def_file_module *m = fdef->modules;
+
+      fdef->modules = fdef->modules->next;
       free (m);
     }
 
-  free (def);
+  while (fdef->aligncomms)
+    {
+      def_file_aligncomm *c = fdef->aligncomms;
+
+      fdef->aligncomms = fdef->aligncomms->next;
+      free (c->symbol_name);
+      free (c);
+    }
+
+  free (fdef);
 }
 
 #ifdef DEF_FILE_PRINT
 void
-def_file_print (FILE *file, def_file *def)
+def_file_print (FILE *file, def_file *fdef)
 {
   int i;
 
-  fprintf (file, ">>>> def_file at 0x%08x\n", def);
-  if (def->name)
-    fprintf (file, "  name: %s\n", def->name ? def->name : "(unspecified)");
-  if (def->is_dll != -1)
-    fprintf (file, "  is dll: %s\n", def->is_dll ? "yes" : "no");
-  if (def->base_address != (bfd_vma) -1)
-    fprintf (file, "  base address: 0x%08x\n", def->base_address);
-  if (def->description)
-    fprintf (file, "  description: `%s'\n", def->description);
-  if (def->stack_reserve != -1)
-    fprintf (file, "  stack reserve: 0x%08x\n", def->stack_reserve);
-  if (def->stack_commit != -1)
-    fprintf (file, "  stack commit: 0x%08x\n", def->stack_commit);
-  if (def->heap_reserve != -1)
-    fprintf (file, "  heap reserve: 0x%08x\n", def->heap_reserve);
-  if (def->heap_commit != -1)
-    fprintf (file, "  heap commit: 0x%08x\n", def->heap_commit);
-
-  if (def->num_section_defs > 0)
+  fprintf (file, ">>>> def_file at 0x%08x\n", fdef);
+  if (fdef->name)
+    fprintf (file, "  name: %s\n", fdef->name ? fdef->name : "(unspecified)");
+  if (fdef->is_dll != -1)
+    fprintf (file, "  is dll: %s\n", fdef->is_dll ? "yes" : "no");
+  if (fdef->base_address != (bfd_vma) -1)
+    {
+      fprintf (file, "  base address: 0x");
+      fprintf_vma (file, fdef->base_address);
+      fprintf (file, "\n");
+    }
+  if (fdef->description)
+    fprintf (file, "  description: `%s'\n", fdef->description);
+  if (fdef->stack_reserve != -1)
+    fprintf (file, "  stack reserve: 0x%08x\n", fdef->stack_reserve);
+  if (fdef->stack_commit != -1)
+    fprintf (file, "  stack commit: 0x%08x\n", fdef->stack_commit);
+  if (fdef->heap_reserve != -1)
+    fprintf (file, "  heap reserve: 0x%08x\n", fdef->heap_reserve);
+  if (fdef->heap_commit != -1)
+    fprintf (file, "  heap commit: 0x%08x\n", fdef->heap_commit);
+
+  if (fdef->num_section_defs > 0)
     {
       fprintf (file, "  section defs:\n");
 
-      for (i = 0; i < def->num_section_defs; i++)
+      for (i = 0; i < fdef->num_section_defs; i++)
        {
          fprintf (file, "    name: `%s', class: `%s', flags:",
-                  def->section_defs[i].name, def->section_defs[i].class);
-         if (def->section_defs[i].flag_read)
+                  fdef->section_defs[i].name, fdef->section_defs[i].class);
+         if (fdef->section_defs[i].flag_read)
            fprintf (file, " R");
-         if (def->section_defs[i].flag_write)
+         if (fdef->section_defs[i].flag_write)
            fprintf (file, " W");
-         if (def->section_defs[i].flag_execute)
+         if (fdef->section_defs[i].flag_execute)
            fprintf (file, " X");
-         if (def->section_defs[i].flag_shared)
+         if (fdef->section_defs[i].flag_shared)
            fprintf (file, " S");
          fprintf (file, "\n");
        }
     }
 
-  if (def->num_exports > 0)
+  if (fdef->num_exports > 0)
     {
       fprintf (file, "  exports:\n");
 
-      for (i = 0; i < def->num_exports; i++)
+      for (i = 0; i < fdef->num_exports; i++)
        {
          fprintf (file, "    name: `%s', int: `%s', ordinal: %d, flags:",
-                  def->exports[i].name, def->exports[i].internal_name,
-                  def->exports[i].ordinal);
-         if (def->exports[i].flag_private)
+                  fdef->exports[i].name, fdef->exports[i].internal_name,
+                  fdef->exports[i].ordinal);
+         if (fdef->exports[i].flag_private)
            fprintf (file, " P");
-         if (def->exports[i].flag_constant)
+         if (fdef->exports[i].flag_constant)
            fprintf (file, " C");
-         if (def->exports[i].flag_noname)
+         if (fdef->exports[i].flag_noname)
            fprintf (file, " N");
-         if (def->exports[i].flag_data)
+         if (fdef->exports[i].flag_data)
            fprintf (file, " D");
          fprintf (file, "\n");
        }
     }
 
-  if (def->num_imports > 0)
+  if (fdef->num_imports > 0)
     {
       fprintf (file, "  imports:\n");
 
-      for (i = 0; i < def->num_imports; i++)
+      for (i = 0; i < fdef->num_imports; i++)
        {
          fprintf (file, "    int: %s, from: `%s', name: `%s', ordinal: %d\n",
-                  def->imports[i].internal_name,
-                  def->imports[i].module,
-                  def->imports[i].name,
-                  def->imports[i].ordinal);
+                  fdef->imports[i].internal_name,
+                  fdef->imports[i].module,
+                  fdef->imports[i].name,
+                  fdef->imports[i].ordinal);
        }
     }
 
-  if (def->version_major != -1)
-    fprintf (file, "  version: %d.%d\n", def->version_major, def->version_minor);
+  if (fdef->version_major != -1)
+    fprintf (file, "  version: %d.%d\n", fdef->version_major, fdef->version_minor);
 
-  fprintf (file, "<<<< def_file at 0x%08x\n", def);
+  fprintf (file, "<<<< def_file at 0x%08x\n", fdef);
 }
 #endif
 
+/* Helper routine to check for identity of string pointers,
+   which might be NULL.  */
+
+static int
+are_names_equal (const char *s1, const char *s2)
+{
+  if (!s1 && !s2)
+    return 0;
+  if (!s1 || !s2)
+    return (!s1 ? -1 : 1);
+  return strcmp (s1, s2);
+}
+
+static int
+cmp_export_elem (const def_file_export *e, const char *ex_name,
+                const char *in_name, const char *its_name,
+                int ord)
+{
+  int r;
+
+  if ((r = are_names_equal (ex_name, e->name)) != 0)
+    return r;
+  if ((r = are_names_equal (in_name, e->internal_name)) != 0)
+    return r;
+  if ((r = are_names_equal (its_name, e->its_name)) != 0)
+    return r;
+  return (ord - e->ordinal);
+}
+
+/* Search the position of the identical element, or returns the position
+   of the next higher element. If last valid element is smaller, then MAX
+   is returned.  */
+
+static int
+find_export_in_list (def_file_export *b, int max,
+                    const char *ex_name, const char *in_name,
+                    const char *its_name, int ord, int *is_ident)
+{
+  int e, l, r, p;
+
+  *is_ident = 0;
+  if (!max)
+    return 0;
+  if ((e = cmp_export_elem (b, ex_name, in_name, its_name, ord)) <= 0)
+    {
+      if (!e)
+       *is_ident = 1;
+      return 0;
+    }
+  if (max == 1)
+    return 1;
+  if ((e = cmp_export_elem (b + (max - 1), ex_name, in_name, its_name, ord)) > 0)
+    return max;
+  else if (!e || max == 2)
+    {
+      if (!e)
+       *is_ident = 1;
+      return max - 1;
+    }
+  l = 0; r = max - 1;
+  while (l < r)
+    {
+      p = (l + r) / 2;
+      e = cmp_export_elem (b + p, ex_name, in_name, its_name, ord);
+      if (!e)
+       {
+         *is_ident = 1;
+         return p;
+       }
+      else if (e < 0)
+       r = p - 1;
+      else if (e > 0)
+       l = p + 1;
+    }
+  if ((e = cmp_export_elem (b + l, ex_name, in_name, its_name, ord)) > 0)
+    ++l;
+  else if (!e)
+    *is_ident = 1;
+  return l;
+}
+
 def_file_export *
-def_file_add_export (def_file *def,
+def_file_add_export (def_file *fdef,
                     const char *external_name,
                     const char *internal_name,
-                    int ordinal)
+                    int ordinal,
+                    const char *its_name,
+                    int *is_dup)
 {
   def_file_export *e;
-  int max_exports = ROUND_UP(def->num_exports, 32);
+  int pos;
+  int max_exports = ROUND_UP(fdef->num_exports, 32);
 
-  if (def->num_exports >= max_exports)
+  if (internal_name && !external_name)
+    external_name = internal_name;
+  if (external_name && !internal_name)
+    internal_name = external_name;
+
+  /* We need to avoid duplicates.  */
+  *is_dup = 0;
+  pos = find_export_in_list (fdef->exports, fdef->num_exports,
+                    external_name, internal_name,
+                    its_name, ordinal, is_dup);
+
+  if (*is_dup != 0)
+    return (fdef->exports + pos);
+
+  if (fdef->num_exports >= max_exports)
     {
-      max_exports = ROUND_UP(def->num_exports + 1, 32);
-      if (def->exports)
-       def->exports = xrealloc (def->exports,
+      max_exports = ROUND_UP(fdef->num_exports + 1, 32);
+      if (fdef->exports)
+       fdef->exports = xrealloc (fdef->exports,
                                 max_exports * sizeof (def_file_export));
       else
-       def->exports = xmalloc (max_exports * sizeof (def_file_export));
+       fdef->exports = xmalloc (max_exports * sizeof (def_file_export));
     }
-  e = def->exports + def->num_exports;
+
+  e = fdef->exports + pos;
+  if (pos != fdef->num_exports)
+    memmove (&e[1], e, (sizeof (def_file_export) * (fdef->num_exports - pos)));
   memset (e, 0, sizeof (def_file_export));
-  if (internal_name && !external_name)
-    external_name = internal_name;
-  if (external_name && !internal_name)
-    internal_name = external_name;
   e->name = xstrdup (external_name);
   e->internal_name = xstrdup (internal_name);
+  e->its_name = (its_name ? xstrdup (its_name) : NULL);
   e->ordinal = ordinal;
-  def->num_exports++;
+  fdef->num_exports++;
   return e;
 }
 
 def_file_module *
-def_get_module (def_file *def, const char *name)
+def_get_module (def_file *fdef, const char *name)
 {
   def_file_module *s;
 
-  for (s = def->modules; s; s = s->next)
+  for (s = fdef->modules; s; s = s->next)
     if (strcmp (s->name, name) == 0)
       return s;
 
@@ -511,52 +723,213 @@ def_get_module (def_file *def, const char *name)
 }
 
 static def_file_module *
-def_stash_module (def_file *def, const char *name)
+def_stash_module (def_file *fdef, const char *name)
 {
   def_file_module *s;
 
-  if ((s = def_get_module (def, name)) != NULL)
+  if ((s = def_get_module (fdef, name)) != NULL)
       return s;
   s = xmalloc (sizeof (def_file_module) + strlen (name));
-  s->next = def->modules;
-  def->modules = s;
+  s->next = fdef->modules;
+  fdef->modules = s;
   s->user_data = 0;
   strcpy (s->name, name);
   return s;
 }
 
-def_file_import *
-def_file_add_import (def_file *def,
-                    const char *name,
-                    const char *module,
-                    int ordinal,
-                    const char *internal_name)
+static int
+cmp_import_elem (const def_file_import *e, const char *ex_name,
+                const char *in_name, const char *module,
+                int ord)
 {
-  def_file_import *i;
-  int max_imports = ROUND_UP (def->num_imports, 16);
+  int r;
+
+  if ((r = are_names_equal (module, (e->module ? e->module->name : NULL))))
+    return r;
+  if ((r = are_names_equal (ex_name, e->name)) != 0)
+    return r;
+  if ((r = are_names_equal (in_name, e->internal_name)) != 0)
+    return r;
+  if (ord != e->ordinal)
+    return (ord < e->ordinal ? -1 : 1);
+  return 0;
+}
 
-  if (def->num_imports >= max_imports)
-    {
-      max_imports = ROUND_UP (def->num_imports+1, 16);
+/* Search the position of the identical element, or returns the position
+   of the next higher element. If last valid element is smaller, then MAX
+   is returned.  */
 
-      if (def->imports)
-       def->imports = xrealloc (def->imports,
-                                max_imports * sizeof (def_file_import));
-      else
-       def->imports = xmalloc (max_imports * sizeof (def_file_import));
+static int
+find_import_in_list (def_file_import *b, int max,
+                    const char *ex_name, const char *in_name,
+                    const char *module, int ord, int *is_ident)
+{
+  int e, l, r, p;
+
+  *is_ident = 0;
+  if (!max)
+    return 0;
+  if ((e = cmp_import_elem (b, ex_name, in_name, module, ord)) <= 0)
+    {
+      if (!e)
+       *is_ident = 1;
+      return 0;
+    }
+  if (max == 1)
+    return 1;
+  if ((e = cmp_import_elem (b + (max - 1), ex_name, in_name, module, ord)) > 0)
+    return max;
+  else if (!e || max == 2)
+    {
+      if (!e)
+       *is_ident = 1;
+      return max - 1;
+    }
+  l = 0; r = max - 1;
+  while (l < r)
+    {
+      p = (l + r) / 2;
+      e = cmp_import_elem (b + p, ex_name, in_name, module, ord);
+      if (!e)
+       {
+         *is_ident = 1;
+         return p;
+       }
+      else if (e < 0)
+       r = p - 1;
+      else if (e > 0)
+       l = p + 1;
     }
-  i = def->imports + def->num_imports;
+  if ((e = cmp_import_elem (b + l, ex_name, in_name, module, ord)) > 0)
+    ++l;
+  else if (!e)
+    *is_ident = 1;
+  return l;
+}
+
+static void
+fill_in_import (def_file_import *i,
+               const char *name,
+               def_file_module *module,
+               int ordinal,
+               const char *internal_name,
+               const char *its_name)
+{
   memset (i, 0, sizeof (def_file_import));
   if (name)
     i->name = xstrdup (name);
-  if (module)
-    i->module = def_stash_module (def, module);
+  i->module = module;
   i->ordinal = ordinal;
   if (internal_name)
     i->internal_name = xstrdup (internal_name);
   else
     i->internal_name = i->name;
-  def->num_imports++;
+  i->its_name = (its_name ? xstrdup (its_name) : NULL);
+}
+
+def_file_import *
+def_file_add_import (def_file *fdef,
+                    const char *name,
+                    const char *module,
+                    int ordinal,
+                    const char *internal_name,
+                    const char *its_name,
+                    int *is_dup)
+{
+  def_file_import *i;
+  int pos;
+  int max_imports = ROUND_UP (fdef->num_imports, 16);
+
+  /* We need to avoid here duplicates.  */
+  *is_dup = 0;
+  pos = find_import_in_list (fdef->imports, fdef->num_imports,
+                            name,
+                            (!internal_name ? name : internal_name),
+                            module, ordinal, is_dup);
+  if (*is_dup != 0)
+    return fdef->imports + pos;
+
+  if (fdef->num_imports >= max_imports)
+    {
+      max_imports = ROUND_UP (fdef->num_imports+1, 16);
+
+      if (fdef->imports)
+       fdef->imports = xrealloc (fdef->imports,
+                                max_imports * sizeof (def_file_import));
+      else
+       fdef->imports = xmalloc (max_imports * sizeof (def_file_import));
+    }
+  i = fdef->imports + pos;
+  if (pos != fdef->num_imports)
+    memmove (i + 1, i, sizeof (def_file_import) * (fdef->num_imports - pos));
+
+  fill_in_import (i, name, def_stash_module (fdef, module), ordinal,
+                 internal_name, its_name);
+  fdef->num_imports++;
+
+  return i;
+}
+
+int
+def_file_add_import_from (def_file *fdef,
+                         int num_imports,
+                         const char *name,
+                         const char *module,
+                         int ordinal,
+                         const char *internal_name,
+                         const char *its_name ATTRIBUTE_UNUSED)
+{
+  def_file_import *i;
+  int is_dup;
+  int pos;
+  int max_imports = ROUND_UP (fdef->num_imports, 16);
+
+  /* We need to avoid here duplicates.  */
+  is_dup = 0;
+  pos = find_import_in_list (fdef->imports, fdef->num_imports,
+                            name, internal_name ? internal_name : name,
+                            module, ordinal, &is_dup);
+  if (is_dup != 0)
+    return -1;
+  if (fdef->imports && pos != fdef->num_imports)
+    {
+      i = fdef->imports + pos;
+      if (i->module && strcmp (i->module->name, module) == 0)
+       return -1;
+    }
+
+  if (fdef->num_imports + num_imports - 1 >= max_imports)
+    {
+      max_imports = ROUND_UP (fdef->num_imports + num_imports, 16);
+
+      if (fdef->imports)
+       fdef->imports = xrealloc (fdef->imports,
+                                max_imports * sizeof (def_file_import));
+      else
+       fdef->imports = xmalloc (max_imports * sizeof (def_file_import));
+    }
+  i = fdef->imports + pos;
+  if (pos != fdef->num_imports)
+    memmove (i + num_imports, i,
+            sizeof (def_file_import) * (fdef->num_imports - pos));
+
+  return pos;
+}
+
+def_file_import *
+def_file_add_import_at (def_file *fdef,
+                       int pos,
+                       const char *name,
+                       const char *module,
+                       int ordinal,
+                       const char *internal_name,
+                       const char *its_name)
+{
+  def_file_import *i = fdef->imports + pos;
+
+  fill_in_import (i, name, def_stash_module (fdef, module), ordinal,
+                 internal_name, its_name);
+  fdef->num_imports++;
 
   return i;
 }
@@ -569,9 +942,10 @@ struct
 diropts[] =
 {
   { "-heap", HEAPSIZE },
-  { "-stack", STACKSIZE },
+  { "-stack", STACKSIZE_K },
   { "-attr", SECTIONS },
   { "-export", EXPORTS },
+  { "-aligncomm", ALIGNCOMM },
   { 0, 0 }
 };
 
@@ -595,10 +969,10 @@ def_file_add_directive (def_file *my_def, const char *param, int len)
        break;
 
       /* Scan forward until we encounter any of:
-          - the end of the buffer
+         - the end of the buffer
          - the start of a new option
-         - a newline seperating options
-          - a NUL seperating options.  */
+         - a newline separating options
+         - a NUL separating options.  */
       for (tend = (char *) (param + 1);
           (tend < pend
            && !(ISSPACE (tend[-1]) && *tend == '-')
@@ -608,7 +982,7 @@ def_file_add_directive (def_file *my_def, const char *param, int len)
 
       for (i = 0; diropts[i].param; i++)
        {
-         int len = strlen (diropts[i].param);
+         len = strlen (diropts[i].param);
 
          if (tend - param >= len
              && strncmp (param, diropts[i].param, len) == 0
@@ -626,13 +1000,20 @@ def_file_add_directive (def_file *my_def, const char *param, int len)
 
       if (!diropts[i].param)
        {
-         char saved;
+         if (tend < pend)
+           {
+             char saved;
 
-         saved = * tend;
-         * tend = 0;
-         /* xgettext:c-format */
-         einfo (_("Warning: .drectve `%s' unrecognized\n"), param);
-         * tend = saved;
+             saved = * tend;
+             * tend = 0;
+             /* xgettext:c-format */
+             einfo (_("Warning: .drectve `%s' unrecognized\n"), param);
+             * tend = saved;
+           }
+         else
+           {
+             einfo (_("Warning: corrupt .drectve at end of def file\n"));
+           }
        }
 
       lex_parse_string = 0;
@@ -640,32 +1021,33 @@ def_file_add_directive (def_file *my_def, const char *param, int len)
     }
 
   def = save_def;
+  def_pool_free ();
 }
 
 /* Parser Callbacks.  */
 
 static void
-def_image_name (const char *name, int base, int is_dll)
+def_image_name (const char *name, bfd_vma base, int is_dll)
 {
   /* If a LIBRARY or NAME statement is specified without a name, there is nothing
      to do here.  We retain the output filename specified on command line.  */
   if (*name)
     {
       const char* image_name = lbasename (name);
+
       if (image_name != name)
        einfo ("%s:%d: Warning: path components stripped from %s, '%s'\n",
               def_filename, linenumber, is_dll ? "LIBRARY" : "NAME",
               name);
-      if (def->name)
-       free (def->name);
-      /* Append the default suffix, if none specified.  */ 
+      free (def->name);
+      /* Append the default suffix, if none specified.  */
       if (strchr (image_name, '.') == 0)
        {
          const char * suffix = is_dll ? ".dll" : ".exe";
 
          def->name = xmalloc (strlen (image_name) + strlen (suffix) + 1);
          sprintf (def->name, "%s%s", image_name, suffix);
-        }
+       }
       else
        def->name = xstrdup (image_name);
     }
@@ -772,9 +1154,11 @@ static void
 def_exports (const char *external_name,
             const char *internal_name,
             int ordinal,
-            int flags)
+            int flags,
+            const char *its_name)
 {
   def_file_export *dfe;
+  int is_dup = 0;
 
   if (!internal_name && external_name)
     internal_name = external_name;
@@ -782,7 +1166,14 @@ def_exports (const char *external_name,
   printf ("def_exports, ext=%s int=%s\n", external_name, internal_name);
 #endif
 
-  dfe = def_file_add_export (def, external_name, internal_name, ordinal);
+  dfe = def_file_add_export (def, external_name, internal_name, ordinal,
+                            its_name, &is_dup);
+
+  /* We might check here for flag redefinition and warn.  For now we
+     ignore duplicates silently.  */
+  if (is_dup)
+    return;
+
   if (flags & 1)
     dfe->flag_noname = 1;
   if (flags & 2)
@@ -798,18 +1189,20 @@ def_import (const char *internal_name,
            const char *module,
            const char *dllext,
            const char *name,
-           int ordinal)
+           int ordinal,
+           const char *its_name)
 {
   char *buf = 0;
-  const char *ext = dllext ? dllext : "dll";    
-   
+  const char *ext = dllext ? dllext : "dll";
+  int is_dup = 0;
+
   buf = xmalloc (strlen (module) + strlen (ext) + 2);
   sprintf (buf, "%s.%s", module, ext);
   module = buf;
 
-  def_file_add_import (def, name, module, ordinal, internal_name);
-  if (buf)
-    free (buf);
+  def_file_add_import (def, name, module, ordinal, internal_name, its_name,
+                      &is_dup);
+  free (buf);
 }
 
 static void
@@ -830,6 +1223,44 @@ def_directive (char *str)
   d->len = strlen (str);
 }
 
+static void
+def_aligncomm (char *str, int align)
+{
+  def_file_aligncomm *c, *p;
+
+  p = NULL;
+  c = def->aligncomms;
+  while (c != NULL)
+    {
+      int e = strcmp (c->symbol_name, str);
+      if (!e)
+       {
+         /* Not sure if we want to allow here duplicates with
+            different alignments, but for now we keep them.  */
+         e = (int) c->alignment - align;
+         if (!e)
+           return;
+       }
+      if (e > 0)
+       break;
+      c = (p = c)->next;
+    }
+
+  c = xmalloc (sizeof (def_file_aligncomm));
+  c->symbol_name = xstrdup (str);
+  c->alignment = (unsigned int) align;
+  if (!p)
+    {
+      c->next = def->aligncomms;
+      def->aligncomms = c;
+    }
+  else
+    {
+      c->next = p->next;
+      p->next = c;
+    }
+}
+
 static int
 def_error (const char *err)
 {
@@ -893,7 +1324,7 @@ tokens[] =
   { "SECTIONS", SECTIONS },
   { "SEGMENTS", SECTIONS },
   { "SHARED", SHARED },
-  { "STACKSIZE", STACKSIZE },
+  { "STACKSIZE", STACKSIZE_K },
   { "VERSION", VERSIONK },
   { "WRITE", WRITE },
   { 0, 0 }
@@ -986,11 +1417,11 @@ def_lex (void)
        }
       if (c != EOF)
        def_ungetc (c);
-      yylval.number = strtoul (buffer, 0, 0);
+      yylval.digits = def_pool_strdup (buffer);
 #if TRACE
-      printf ("lex: `%s' returns NUMBER %d\n", buffer, yylval.number);
+      printf ("lex: `%s' returns DIGITS\n", buffer);
 #endif
-      return NUMBER;
+      return DIGITS;
     }
 
   if (ISALPHA (c) || strchr ("$:-_?@", c))
@@ -1002,19 +1433,19 @@ def_lex (void)
 
       if (q == '@')
        {
-          if (ISBLANK (c) ) /* '@' followed by whitespace.  */
+         if (ISBLANK (c) ) /* '@' followed by whitespace.  */
            return (q);
-          else if (ISDIGIT (c)) /* '@' followed by digit.  */
-            {
+         else if (ISDIGIT (c)) /* '@' followed by digit.  */
+           {
              def_ungetc (c);
-              return (q);
+             return (q);
            }
 #if TRACE
          printf ("lex: @ returns itself\n");
 #endif
        }
 
-      while (c != EOF && (ISALNUM (c) || strchr ("$:-_?/@", c)))
+      while (c != EOF && (ISALNUM (c) || strchr ("$:-_?/@<>", c)))
        {
          put_buf (c);
          c = def_getc ();
@@ -1023,7 +1454,7 @@ def_lex (void)
        def_ungetc (c);
       if (ISALPHA (q)) /* Check for tokens.  */
        {
-          for (i = 0; tokens[i].name; i++)
+         for (i = 0; tokens[i].name; i++)
            if (strcmp (tokens[i].name, buffer) == 0)
              {
 #if TRACE
@@ -1035,7 +1466,7 @@ def_lex (void)
 #if TRACE
       printf ("lex: `%s' returns ID\n", buffer);
 #endif
-      yylval.id = xstrdup (buffer);
+      yylval.id = def_pool_strdup (buffer);
       return ID;
     }
 
@@ -1050,14 +1481,30 @@ def_lex (void)
          put_buf (c);
          c = def_getc ();
        }
-      yylval.id = xstrdup (buffer);
+      yylval.id = def_pool_strdup (buffer);
 #if TRACE
       printf ("lex: `%s' returns ID\n", buffer);
 #endif
       return ID;
     }
 
-  if (c == '=' || c == '.' || c == ',')
+  if ( c == '=')
+    {
+      c = def_getc ();
+      if (c == '=')
+       {
+#if TRACE
+         printf ("lex: `==' returns EQUAL\n");
+#endif
+         return EQUAL;
+       }
+      def_ungetc (c);
+#if TRACE
+      printf ("lex: `=' returns itself\n");
+#endif
+      return '=';
+    }
+  if (c == '.' || c == ',')
     {
 #if TRACE
       printf ("lex: `%c' returns itself\n", c);
@@ -1074,3 +1521,38 @@ def_lex (void)
   /*printf ("lex: 0x%02x ignored\n", c); */
   return def_lex ();
 }
+
+static char *
+def_pool_alloc (size_t sz)
+{
+  def_pool_str *e;
+
+  e = (def_pool_str *) xmalloc (sizeof (def_pool_str) + sz);
+  e->next = pool_strs;
+  pool_strs = e;
+  return e->data;
+}
+
+static char *
+def_pool_strdup (const char *str)
+{
+  char *s;
+  size_t len;
+  if (!str)
+    return NULL;
+  len = strlen (str) + 1;
+  s = def_pool_alloc (len);
+  memcpy (s, str, len);
+  return s;
+}
+
+static void
+def_pool_free (void)
+{
+  def_pool_str *p;
+  while ((p = pool_strs) != NULL)
+    {
+      pool_strs = p->next;
+      free (p);
+    }
+}
This page took 0.03913 seconds and 4 git commands to generate.