ld/testsuite/
[platform/upstream/binutils.git] / ld / ldgram.y
index 23151d8..f481f54 100644 (file)
@@ -1,13 +1,13 @@
 /* A YACC grammar to parse a superset of the AT&T linker scripting language.
    Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
-   2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+   2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
    Written by Steve Chamberlain of Cygnus Support (steve@cygnus.com).
 
-   This file is part of GNU ld.
+   This file is part of the 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,
@@ -17,7 +17,8 @@
 
    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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+   MA 02110-1301, USA.  */
 
 %{
 /*
@@ -26,8 +27,8 @@
 
 #define DONTDECLARE_MALLOC
 
-#include "bfd.h"
 #include "sysdep.h"
+#include "bfd.h"
 #include "bfdlink.h"
 #include "ld.h"
 #include "ldexp.h"
 #endif
 
 static enum section_type sectype;
+static lang_memory_region_type *region;
 
-lang_memory_region_type *region;
-
-bfd_boolean ldgram_want_filename = TRUE;
-FILE *saved_script_handle = NULL;
-bfd_boolean force_make_executable = FALSE;
-
-bfd_boolean ldgram_in_script = FALSE;
-bfd_boolean ldgram_had_equals = FALSE;
 bfd_boolean ldgram_had_keep = FALSE;
 char *ldgram_vers_current_lang = NULL;
 
@@ -94,7 +88,7 @@ static int error_index;
 }
 
 %type <etree> exp opt_exp_with_type mustbe_exp opt_at phdr_type phdr_val
-%type <etree> opt_exp_without_type opt_subalign
+%type <etree> opt_exp_without_type opt_subalign opt_align
 %type <fill> fill_opt fill_exp
 %type <name_list> exclude_name_list
 %type <wildcard_list> file_NAME_list
@@ -128,23 +122,23 @@ static int error_index;
 %token END
 %left <token> '('
 %token <token> ALIGN_K BLOCK BIND QUAD SQUAD LONG SHORT BYTE
-%token SECTIONS PHDRS DATA_SEGMENT_ALIGN DATA_SEGMENT_RELRO_END DATA_SEGMENT_END
+%token SECTIONS PHDRS INSERT_K AFTER BEFORE
+%token DATA_SEGMENT_ALIGN DATA_SEGMENT_RELRO_END DATA_SEGMENT_END
 %token SORT_BY_NAME SORT_BY_ALIGNMENT
 %token '{' '}'
 %token SIZEOF_HEADERS OUTPUT_FORMAT FORCE_COMMON_ALLOCATION OUTPUT_ARCH
 %token INHIBIT_COMMON_ALLOCATION
-%token SIZEOF_HEADERS
 %token SEGMENT_START
 %token INCLUDE
-%token MEMORY DEFSYMEND
+%token MEMORY
 %token NOLOAD DSECT COPY INFO OVERLAY
-%token NAME LNAME DEFINED TARGET_K SEARCH_DIR MAP ENTRY
+%token DEFINED TARGET_K SEARCH_DIR MAP ENTRY
 %token <integer> NEXT
-%token SIZEOF ADDR LOADADDR MAX_K MIN_K
+%token SIZEOF ALIGNOF ADDR LOADADDR MAX_K MIN_K
 %token STARTUP HLL SYSLIB FLOAT NOFLOAT NOCROSSREFS
 %token ORIGIN FILL
 %token LENGTH CREATE_OBJECT_SYMBOLS INPUT GROUP OUTPUT CONSTRUCTORS
-%token ALIGNMOD AT SUBALIGN PROVIDE AS_NEEDED
+%token ALIGNMOD AT SUBALIGN PROVIDE PROVIDE_HIDDEN AS_NEEDED
 %type <token> assign_op atype attributes_opt sect_constraint
 %type <name>  filename
 %token CHIP LIST SECT ABSOLUTE  LOAD NEWLINE ENDWORD ORDER NAMEWORD ASSERT_K
@@ -152,11 +146,13 @@ static int error_index;
 %token INPUT_SCRIPT INPUT_MRI_SCRIPT INPUT_DEFSYM CASE EXTERN START
 %token <name> VERS_TAG VERS_IDENTIFIER
 %token GLOBAL LOCAL VERSIONK INPUT_VERSION_SCRIPT
-%token KEEP ONLY_IF_RO ONLY_IF_RW
+%token KEEP ONLY_IF_RO ONLY_IF_RW SPECIAL
 %token EXCLUDE_FILE
+%token CONSTANT
 %type <versyms> vers_defns
 %type <versnode> vers_tag
 %type <deflist> verdep
+%token INPUT_DYNAMIC_LIST
 
 %%
 
@@ -164,6 +160,7 @@ file:
                INPUT_SCRIPT script_file
        |       INPUT_MRI_SCRIPT mri_script_file
        |       INPUT_VERSION_SCRIPT version_script_file
+       |       INPUT_DYNAMIC_LIST dynamic_list_file
        |       INPUT_DEFSYM defsym_expr
        ;
 
@@ -280,33 +277,33 @@ casesymlist:
        | casesymlist ',' NAME
        ;
 
+/* Parsed as expressions so that commas separate entries */
 extern_name_list:
+       { ldlex_expression (); }
+       extern_name_list_body
+       { ldlex_popstate (); }
+
+extern_name_list_body:
          NAME
                        { ldlang_add_undef ($1); }
-       | extern_name_list NAME
+       | extern_name_list_body NAME
                        { ldlang_add_undef ($2); }
-       | extern_name_list ',' NAME
+       | extern_name_list_body ',' NAME
                        { ldlang_add_undef ($3); }
        ;
 
 script_file:
-       {
-        ldlex_both();
-       }
-       ifile_list
-       {
-       ldlex_popstate();
-       }
+       { ldlex_both(); }
+       ifile_list
+       { ldlex_popstate(); }
         ;
 
-
 ifile_list:
-       ifile_list ifile_p1
+       ifile_list ifile_p1
         |
        ;
 
 
-
 ifile_p1:
                memory
        |       sections
@@ -351,6 +348,10 @@ ifile_p1:
                  lang_add_nocrossref ($3);
                }
        |       EXTERN '(' extern_name_list ')'
+       |       INSERT_K AFTER NAME
+               { lang_add_insert ($3, 0); }
+       |       INSERT_K BEFORE NAME
+               { lang_add_insert ($3, 1); }
        ;
 
 input_list:
@@ -573,6 +574,9 @@ statement:
                        {
                          lang_add_fill ($3);
                        }
+       | ASSERT_K  {ldlex_expression ();} '(' exp ',' NAME ')' end
+                       { ldlex_popstate ();
+                         lang_add_assignment (exp_assert ($4, $6)); }
        ;
 
 statement_list:
@@ -601,10 +605,7 @@ length:
 fill_exp:
        mustbe_exp
                {
-                 $$ = exp_get_fill ($1,
-                                    0,
-                                    "fill value",
-                                    lang_first_phase_enum);
+                 $$ = exp_get_fill ($1, 0, "fill value");
                }
        ;
 
@@ -653,7 +654,11 @@ assignment:
                }
        |       PROVIDE '(' NAME '=' mustbe_exp ')'
                {
-                 lang_add_assignment (exp_provide ($3, $5));
+                 lang_add_assignment (exp_provide ($3, $5, FALSE));
+               }
+       |       PROVIDE_HIDDEN '(' NAME '=' mustbe_exp ')'
+               {
+                 lang_add_assignment (exp_provide ($3, $5, TRUE));
                }
        ;
 
@@ -682,18 +687,16 @@ memory_spec:      NAME
 
 origin_spec:
        ORIGIN '=' mustbe_exp
-               { region->current =
-                region->origin =
-                exp_get_vma($3, 0L,"origin", lang_first_phase_enum);
-}
+               {
+                 region->origin = exp_get_vma ($3, 0, "origin");
+                 region->current = region->origin;
+               }
        ;
 
 length_spec:
              LENGTH '=' mustbe_exp
-               { region->length = exp_get_vma($3,
-                                              ~((bfd_vma)0),
-                                              "length",
-                                              lang_first_phase_enum);
+               {
+                 region->length = exp_get_vma ($3, -1, "length");
                }
        ;
 
@@ -838,12 +841,16 @@ exp       :
         |      SIZEOF_HEADERS
                        { $$ = exp_nameop (SIZEOF_HEADERS,0); }
 
+       |       ALIGNOF '(' NAME ')'
+                       { $$ = exp_nameop (ALIGNOF,$3); }
        |       SIZEOF '(' NAME ')'
                        { $$ = exp_nameop (SIZEOF,$3); }
        |       ADDR '(' NAME ')'
                        { $$ = exp_nameop (ADDR,$3); }
        |       LOADADDR '(' NAME ')'
                        { $$ = exp_nameop (LOADADDR,$3); }
+       |       CONSTANT '(' NAME ')'
+                       { $$ = exp_nameop (CONSTANT,$3); }
        |       ABSOLUTE '(' exp ')'
                        { $$ = exp_unop (ABSOLUTE, $3); }
        |       ALIGN_K '(' exp ')'
@@ -892,6 +899,11 @@ opt_at:
        |       { $$ = 0; }
        ;
 
+opt_align:
+               ALIGN_K '(' exp ')' { $$ = $3; }
+       |       { $$ = 0; }
+       ;
+
 opt_subalign:
                SUBALIGN '(' exp ')' { $$ = $3; }
        |       { $$ = 0; }
@@ -900,26 +912,28 @@ opt_subalign:
 sect_constraint:
                ONLY_IF_RO { $$ = ONLY_IF_RO; }
        |       ONLY_IF_RW { $$ = ONLY_IF_RW; }
+       |       SPECIAL { $$ = SPECIAL; }
        |       { $$ = 0; }
        ;
 
 section:       NAME            { ldlex_expression(); }
                opt_exp_with_type
                opt_at
+               opt_align
                opt_subalign    { ldlex_popstate (); ldlex_script (); }
                sect_constraint
                '{'
                        {
                          lang_enter_output_section_statement($1, $3,
                                                              sectype,
-                                                             0, $5, $4, $7);
+                                                             $5, $6, $4, $8);
                        }
                statement_list_opt
                '}' { ldlex_popstate (); ldlex_expression (); }
                memspec_opt memspec_at_opt phdr_opt fill_opt
                {
                  ldlex_popstate ();
-                 lang_leave_output_section_statement ($16, $13, $15, $14);
+                 lang_leave_output_section_statement ($17, $14, $16, $15);
                }
                opt_comma
                {}
@@ -956,10 +970,10 @@ section:  NAME            { ldlex_expression(); }
 
 type:
           NOLOAD  { sectype = noload_section; }
-       |  DSECT   { sectype = dsect_section; }
-       |  COPY    { sectype = copy_section; }
-       |  INFO    { sectype = info_section; }
-       |  OVERLAY { sectype = overlay_section; }
+       |  DSECT   { sectype = noalloc_section; }
+       |  COPY    { sectype = noalloc_section; }
+       |  INFO    { sectype = noalloc_section; }
+       |  OVERLAY { sectype = noalloc_section; }
        ;
 
 atype:
@@ -1132,6 +1146,34 @@ phdr_val:
                }
        ;
 
+dynamic_list_file:
+               {
+                 ldlex_version_file ();
+                 PUSH_ERROR (_("dynamic list"));
+               }
+               dynamic_list_nodes
+               {
+                 ldlex_popstate ();
+                 POP_ERROR ();
+               }
+       ;
+
+dynamic_list_nodes:
+               dynamic_list_node
+       |       dynamic_list_nodes dynamic_list_node
+       ;
+
+dynamic_list_node:
+               '{' dynamic_list_tag '}' ';'
+       ;
+
+dynamic_list_tag:
+               vers_defns ';'
+               {
+                 lang_append_dynamic_list ($1);
+               }
+       ;
+
 /* This syntax is used within an external version script file.  */
 
 version_script_file:
@@ -1215,11 +1257,19 @@ vers_tag:
 vers_defns:
                VERS_IDENTIFIER
                {
-                 $$ = lang_new_vers_pattern (NULL, $1, ldgram_vers_current_lang);
+                 $$ = lang_new_vers_pattern (NULL, $1, ldgram_vers_current_lang, FALSE);
+               }
+        |       NAME
+               {
+                 $$ = lang_new_vers_pattern (NULL, $1, ldgram_vers_current_lang, TRUE);
                }
        |       vers_defns ';' VERS_IDENTIFIER
                {
-                 $$ = lang_new_vers_pattern ($1, $3, ldgram_vers_current_lang);
+                 $$ = lang_new_vers_pattern ($1, $3, ldgram_vers_current_lang, FALSE);
+               }
+       |       vers_defns ';' NAME
+               {
+                 $$ = lang_new_vers_pattern ($1, $3, ldgram_vers_current_lang, TRUE);
                }
        |       vers_defns ';' EXTERN NAME '{'
                        {
@@ -1228,6 +1278,9 @@ vers_defns:
                        }
                vers_defns opt_semicolon '}'
                        {
+                         struct bfd_elf_version_expr *pat;
+                         for (pat = $7; pat->next != NULL; pat = pat->next);
+                         pat->next = $1;
                          $$ = $7;
                          ldgram_vers_current_lang = $<name>6;
                        }
@@ -1241,6 +1294,30 @@ vers_defns:
                          $$ = $5;
                          ldgram_vers_current_lang = $<name>4;
                        }
+       |       GLOBAL
+               {
+                 $$ = lang_new_vers_pattern (NULL, "global", ldgram_vers_current_lang, FALSE);
+               }
+       |       vers_defns ';' GLOBAL
+               {
+                 $$ = lang_new_vers_pattern ($1, "global", ldgram_vers_current_lang, FALSE);
+               }
+       |       LOCAL
+               {
+                 $$ = lang_new_vers_pattern (NULL, "local", ldgram_vers_current_lang, FALSE);
+               }
+       |       vers_defns ';' LOCAL
+               {
+                 $$ = lang_new_vers_pattern ($1, "local", ldgram_vers_current_lang, FALSE);
+               }
+       |       EXTERN
+               {
+                 $$ = lang_new_vers_pattern (NULL, "extern", ldgram_vers_current_lang, FALSE);
+               }
+       |       vers_defns ';' EXTERN
+               {
+                 $$ = lang_new_vers_pattern ($1, "extern", ldgram_vers_current_lang, FALSE);
+               }
        ;
 
 opt_semicolon: