]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blobdiff - ld/deffilep.y
Update year range in copyright notice of binutils files
[thirdparty/binutils-gdb.git] / ld / deffilep.y
index a1cd99370b416965364167c4110efa1bdcf416a7..e58d0e0bcb5b855471d7349af7d5fdafd5f8ebb9 100644 (file)
@@ -1,7 +1,6 @@
 %{ /* deffilep.y - parser for .def files */
 
-/*   Copyright 1995, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2005, 2006,
-     2007, 2009 Free Software Foundation, Inc.
+/*   Copyright (C) 1995-2021 Free Software Foundation, Inc.
 
      This file is part of GNU Binutils.
 
@@ -24,6 +23,7 @@
 #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, const char *);
 static void def_heapsize (int, int);
 static void def_import (const char *, const char *, const char *, const char *,
                        int, const char *);
-static void def_image_name (const char *, int, int);
+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);
@@ -102,22 +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_K HEAPSIZE CODE DATAU DATAL
 %token SECTIONS EXPORTS IMPORTS VERSIONK BASE CONSTANTU CONSTANTL
 %token PRIVATEU PRIVATEL ALIGNCOMM
-%token READ WRITE EXECUTE SHARED NONAMEU NONAMEL DIRECTIVE EQUAL
+%token READ WRITE EXECUTE SHARED_K NONAMEU NONAMEL DIRECTIVE EQUAL
 %token <id> ID
 %token <digits> DIGITS
 %type  <number> NUMBER
+%type  <vma> VMA opt_base
 %type  <digits> opt_digits
-%type  <number> opt_base opt_ordinal
+%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 anylang_id opt_id
+%type  <id> opt_name opt_name2 opt_equal_name anylang_id opt_id
 %type  <id> opt_equalequal_name
+%type  <id_const> keyword_as_name
 
 %%
 
@@ -125,7 +140,7 @@ 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);}
@@ -134,7 +149,7 @@ command:
        |       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);}
@@ -153,7 +168,7 @@ 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 opt_comma opt_equalequal_name
+               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:
@@ -173,24 +188,24 @@ exp_opt:
        |       PRIVATEU        { $$ = 8; }
        |       PRIVATEL        { $$ = 8; }
        ;
-implist:       
+implist:
                implist impline
        |       impline
        ;
 
 impline:
-               ID '=' ID '.' ID '.' ID opt_equalequal_name
-                 { def_import ($1, $3, $5, $7, -1, $8); }
+              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); }
+                { def_import ($1, $3,  0, $5, -1, $6); }
        |       ID '=' ID '.' NUMBER opt_equalequal_name
-                 { def_import ($1, $3,  0,  0, $5, $6); }
+                { def_import ($1, $3,  0,  0, $5, $6); }
        |       ID '.' ID '.' ID opt_equalequal_name
-                 { def_import( 0, $1, $3, $5, -1, $6); }
+                { def_import( 0, $1, $3, $5, -1, $6); }
        |       ID '.' ID opt_equalequal_name
-                 { def_import ( 0, $1,  0, $3, -1, $4); }
+                { def_import ( 0, $1,  0, $3, -1, $4); }
 ;
 
 seclist:
@@ -210,32 +225,78 @@ attr_list:
 
 opt_comma:
        ','
-       | 
+       |
        ;
 opt_number: ',' NUMBER { $$=$2;}
        |          { $$=-1;}
        ;
-       
+
 attr:
                READ    { $$ = 1;}
-       |       WRITE   { $$ = 2;}      
+       |       WRITE   { $$ = 2;}
        |       EXECUTE { $$=4;}
-       |       SHARED  { $$=8;}
+       |       SHARED_K { $$=8;}
        ;
 
-opt_name: ID           { $$ = $1; }
-       | '.' ID
+
+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_K  { $$ = "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;
          }
-       | ID '.' ID     
-         { 
-           char *name = xmalloc (strlen ($1) + 1 + strlen ($3) + 1);
+       | '.' 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; }
        |               { $$ = ""; }
        ;
 
@@ -243,45 +304,30 @@ opt_equalequal_name: EQUAL ID     { $$ = $2; }
        |                                                       { $$ = 0; }
        ;
 
-opt_ordinal: 
+opt_ordinal:
          '@' NUMBER     { $$ = $2;}
        |                { $$ = -1;}
        ;
 
 opt_equal_name:
-          '=' dot_name { $$ = $2; }
-        |              { $$ =  0; }                     
+         '=' opt_name2 { $$ = $2; }
+       |               { $$ =  0; }
        ;
 
-opt_base: BASE '=' NUMBER      { $$ = $3;}
-       |       { $$ = -1;}
-       ;
-
-dot_name: ID           { $$ = $1; }
-       | '.' ID
-         {
-           char *name = xmalloc (strlen ($2) + 2);
-           sprintf (name, ".%s", $2);
-           $$ = name;
-         }
-       | dot_name '.' ID       
-         { 
-           char *name = xmalloc (strlen ($1) + 1 + strlen ($3) + 1);
-           sprintf (name, "%s.%s", $1, $3);
-           $$ = name;
-         }
+opt_base: BASE '=' VMA { $$ = $3;}
+       |       { $$ = (bfd_vma) -1;}
        ;
 
 anylang_id: ID         { $$ = $1; }
        | '.' ID
          {
-           char *id = xmalloc (strlen ($2) + 2);
+           char *id = def_pool_alloc (strlen ($2) + 2);
            sprintf (id, ".%s", $2);
            $$ = id;
          }
        | anylang_id '.' opt_digits opt_id
          {
-           char *id = xmalloc (strlen ($1) + 1 + strlen ($3) + strlen ($4) + 1);
+           char *id = def_pool_alloc (strlen ($1) + 1 + strlen ($3) + strlen ($4) + 1);
            sprintf (id, "%s.%s%s", $1, $3, $4);
            $$ = id;
          }
@@ -296,6 +342,8 @@ opt_id: ID          { $$ = $1; }
        ;
 
 NUMBER: DIGITS         { $$ = strtoul ($1, 0, 0); }
+       ;
+VMA: DIGITS            { $$ = (bfd_vma) strtoull ($1, 0, 0); }
 
 %%
 
@@ -358,18 +406,23 @@ 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;
 }
@@ -381,19 +434,15 @@ def_file_free (def_file *fdef)
 
   if (!fdef)
     return;
-  if (fdef->name)
-    free (fdef->name);
-  if (fdef->description)
-    free (fdef->description);
+  free (fdef->name);
+  free (fdef->description);
 
   if (fdef->section_defs)
     {
       for (i = 0; i < fdef->num_section_defs; i++)
        {
-         if (fdef->section_defs[i].name)
-           free (fdef->section_defs[i].name);
-         if (fdef->section_defs[i].class)
-           free (fdef->section_defs[i].class);
+         free (fdef->section_defs[i].name);
+         free (fdef->section_defs[i].class);
        }
       free (fdef->section_defs);
     }
@@ -402,13 +451,10 @@ def_file_free (def_file *fdef)
     {
       for (i = 0; i < fdef->num_exports; i++)
        {
-         if (fdef->exports[i].internal_name
-             && fdef->exports[i].internal_name != fdef->exports[i].name)
+         if (fdef->exports[i].internal_name != fdef->exports[i].name)
            free (fdef->exports[i].internal_name);
-         if (fdef->exports[i].name)
-           free (fdef->exports[i].name);
-         if (fdef->exports[i].its_name)
-           free (fdef->exports[i].its_name);
+         free (fdef->exports[i].name);
+         free (fdef->exports[i].its_name);
        }
       free (fdef->exports);
     }
@@ -417,13 +463,10 @@ def_file_free (def_file *fdef)
     {
       for (i = 0; i < fdef->num_imports; i++)
        {
-         if (fdef->imports[i].internal_name
-             && fdef->imports[i].internal_name != fdef->imports[i].name)
+         if (fdef->imports[i].internal_name != fdef->imports[i].name)
            free (fdef->imports[i].internal_name);
-         if (fdef->imports[i].name)
-           free (fdef->imports[i].name);
-         if (fdef->imports[i].its_name)
-           free (fdef->imports[i].its_name);
+         free (fdef->imports[i].name);
+         free (fdef->imports[i].its_name);
        }
       free (fdef->imports);
     }
@@ -460,7 +503,11 @@ def_file_print (FILE *file, def_file *fdef)
   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%08x\n", fdef->base_address);
+    {
+      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)
@@ -578,27 +625,35 @@ find_export_in_list (def_file_export *b, int max,
   if (!max)
     return 0;
   if ((e = cmp_export_elem (b, ex_name, in_name, its_name, ord)) <= 0)
-    return 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)
-    return max - 1;
+    {
+      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;
-        }
+       {
+         *is_ident = 1;
+         return p;
+       }
       else if (e < 0)
-        r = p - 1;
+       r = p - 1;
       else if (e > 0)
-        l = p + 1;
+       l = p + 1;
     }
   if ((e = cmp_export_elem (b + l, ex_name, in_name, its_name, ord)) > 0)
     ++l;
@@ -689,13 +744,15 @@ cmp_import_elem (const def_file_import *e, const char *ex_name,
 {
   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 are_names_equal (module, (e->module ? e->module->name : NULL));
+  return 0;
 }
 
 /* Search the position of the identical element, or returns the position
@@ -713,27 +770,35 @@ find_import_in_list (def_file_import *b, int max,
   if (!max)
     return 0;
   if ((e = cmp_import_elem (b, ex_name, in_name, module, ord)) <= 0)
-    return 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)
-    return max - 1;
+    {
+      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;
-        }
+       {
+         *is_ident = 1;
+         return p;
+       }
       else if (e < 0)
-        r = p - 1;
+       r = p - 1;
       else if (e > 0)
-        l = p + 1;
+       l = p + 1;
     }
   if ((e = cmp_import_elem (b + l, ex_name, in_name, module, ord)) > 0)
     ++l;
@@ -742,6 +807,26 @@ find_import_in_list (def_file_import *b, int max,
   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);
+  i->module = module;
+  i->ordinal = ordinal;
+  if (internal_name)
+    i->internal_name = xstrdup (internal_name);
+  else
+    i->internal_name = i->name;
+  i->its_name = (its_name ? xstrdup (its_name) : NULL);
+}
+
 def_file_import *
 def_file_add_import (def_file *fdef,
                     const char *name,
@@ -776,18 +861,74 @@ def_file_add_import (def_file *fdef,
     }
   i = fdef->imports + pos;
   if (pos != fdef->num_imports)
-    memmove (&i[1], i, (sizeof (def_file_import) * (fdef->num_imports - pos)));
-  memset (i, 0, sizeof (def_file_import));
-  if (name)
-    i->name = xstrdup (name);
-  if (module)
-    i->module = def_stash_module (fdef, module);
-  i->ordinal = ordinal;
-  if (internal_name)
-    i->internal_name = xstrdup (internal_name);
-  else
-    i->internal_name = i->name;
-  i->its_name = (its_name ? xstrdup (its_name) : NULL);
+    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;
@@ -828,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 == '-')
@@ -859,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;
@@ -873,12 +1021,13 @@ 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.  */
@@ -890,16 +1039,15 @@ def_image_name (const char *name, int base, int is_dll)
        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);
     }
@@ -1047,7 +1195,7 @@ def_import (const char *internal_name,
   char *buf = 0;
   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;
@@ -1078,13 +1226,39 @@ def_directive (char *str)
 static void
 def_aligncomm (char *str, int align)
 {
-  def_file_aligncomm *c = xmalloc (sizeof (def_file_aligncomm));
+  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;
-
-  c->next = def->aligncomms;
-  def->aligncomms = c;
+  if (!p)
+    {
+      c->next = def->aligncomms;
+      def->aligncomms = c;
+    }
+  else
+    {
+      c->next = p->next;
+      p->next = c;
+    }
 }
 
 static int
@@ -1149,7 +1323,7 @@ tokens[] =
   { "READ", READ },
   { "SECTIONS", SECTIONS },
   { "SEGMENTS", SECTIONS },
-  { "SHARED", SHARED },
+  { "SHARED", SHARED_K },
   { "STACKSIZE", STACKSIZE_K },
   { "VERSION", VERSIONK },
   { "WRITE", WRITE },
@@ -1243,7 +1417,7 @@ def_lex (void)
        }
       if (c != EOF)
        def_ungetc (c);
-      yylval.digits = xstrdup (buffer);
+      yylval.digits = def_pool_strdup (buffer);
 #if TRACE
       printf ("lex: `%s' returns DIGITS\n", buffer);
 #endif
@@ -1259,12 +1433,12 @@ 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");
@@ -1280,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
@@ -1292,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;
     }
 
@@ -1307,7 +1481,7 @@ 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
@@ -1318,12 +1492,12 @@ def_lex (void)
     {
       c = def_getc ();
       if (c == '=')
-        {
+       {
 #if TRACE
-          printf ("lex: `==' returns EQUAL\n");
+         printf ("lex: `==' returns EQUAL\n");
 #endif
-                 return EQUAL;
-        }
+         return EQUAL;
+       }
       def_ungetc (c);
 #if TRACE
       printf ("lex: `=' returns itself\n");
@@ -1347,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);
+    }
+}