ld/
[deliverable/binutils-gdb.git] / ld / deffilep.y
index a1cd99370b416965364167c4110efa1bdcf416a7..3afb3ce3ce859ffcd370f53c99afbeadb3136c2e 100644 (file)
 #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);
@@ -102,6 +113,7 @@ static const char *lex_parse_string_end = 0;
 
 %union {
   char *id;
+  const char *id_const;
   int number;
   char *digits;
 };
@@ -116,8 +128,9 @@ static const char *lex_parse_string_end = 0;
 %type  <digits> opt_digits
 %type  <number> opt_base 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
 
 %%
 
@@ -153,7 +166,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:
@@ -223,19 +236,65 @@ attr:
        |       SHARED  { $$=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  { $$ = "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     
+       | '.' opt_name2
+         { 
+           char *name = def_pool_alloc (strlen ($2) + 2);
+           sprintf (name, ".%s", $2);
+           $$ = name;
+         }
+       | keyword_as_name '.' opt_name2
          { 
-           char *name = xmalloc (strlen ($1) + 1 + strlen ($3) + 1);
+           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; }
        |               { $$ = ""; }
        ;
 
@@ -249,7 +308,7 @@ opt_ordinal:
        ;
 
 opt_equal_name:
-          '=' dot_name { $$ = $2; }
+          '=' opt_name2        { $$ = $2; }
         |              { $$ =  0; }                     
        ;
 
@@ -257,31 +316,16 @@ 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;
-         }
-       ;
-
 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;
          }
@@ -358,18 +402,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;
 }
@@ -578,13 +627,21 @@ 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)
     {
@@ -689,13 +746,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,13 +772,21 @@ 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)
     {
@@ -873,6 +940,7 @@ def_file_add_directive (def_file *my_def, const char *param, int len)
     }
 
   def = save_def;
+  def_pool_free ();
 }
 
 /* Parser Callbacks.  */
@@ -1078,13 +1146,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
@@ -1243,7 +1337,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
@@ -1292,7 +1386,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 +1401,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
@@ -1347,3 +1441,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.02694 seconds and 4 git commands to generate.