+ | INCLUDE string
+ { script_include_directive(closure, $2.value, $2.length); }
+ ;
+
+/* A list of MEMORY definitions. */
+memory_defs:
+ memory_defs opt_comma memory_def
+ | /* empty */
+ ;
+
+/* A single MEMORY definition. */
+memory_def:
+ string memory_attr ':' memory_origin '=' parse_exp opt_comma memory_length '=' parse_exp
+ { script_add_memory(closure, $1.value, $1.length, $2, $6, $10); }
+ |
+ /* LD supports an INCLUDE directive here, currently GOLD does not. */
+ INCLUDE string
+ { script_include_directive(closure, $2.value, $2.length); }
+ |
+ ;
+
+/* The (optional) attributes of a MEMORY region. */
+memory_attr:
+ '(' string ')'
+ { $$ = script_parse_memory_attr(closure, $2.value, $2.length, 0); }
+ | /* Inverted attributes. */
+ '(' '!' string ')'
+ { $$ = script_parse_memory_attr(closure, $3.value, $3.length, 1); }
+ | /* empty */
+ { $$ = 0; }
+ ;
+
+memory_origin:
+ ORIGIN
+ |
+ ORG
+ |
+ 'o'
+ ;
+
+memory_length:
+ LENGTH
+ |
+ LEN
+ |
+ 'l'
+ ;
+
+/* A list of program header definitions. */
+phdrs_defs:
+ phdrs_defs phdr_def
+ | /* empty */
+ ;
+
+/* A program header definition. */
+phdr_def:
+ string phdr_type phdr_info ';'
+ { script_add_phdr(closure, $1.value, $1.length, $2, &$3); }
+ ;
+
+/* A program header type. The GNU linker accepts a general expression
+ here, but that would be a pain because we would have to dig into
+ the expression structure. It's unlikely that anybody uses anything
+ other than a string or a number here, so that is all we expect. */
+phdr_type:
+ string
+ { $$ = script_phdr_string_to_type(closure, $1.value, $1.length); }
+ | INTEGER
+ { $$ = $1; }
+ ;
+
+/* Additional information for a program header. */
+phdr_info:
+ /* empty */
+ { memset(&$$, 0, sizeof(struct Phdr_info)); }
+ | string phdr_info
+ {
+ $$ = $2;
+ if ($1.length == 7 && strncmp($1.value, "FILEHDR", 7) == 0)
+ $$.includes_filehdr = 1;
+ else
+ yyerror(closure, "PHDRS syntax error");
+ }
+ | PHDRS phdr_info
+ {
+ $$ = $2;
+ $$.includes_phdrs = 1;
+ }
+ | string '(' INTEGER ')' phdr_info
+ {
+ $$ = $5;
+ if ($1.length == 5 && strncmp($1.value, "FLAGS", 5) == 0)
+ {
+ $$.is_flags_valid = 1;
+ $$.flags = $3;
+ }
+ else
+ yyerror(closure, "PHDRS syntax error");
+ }
+ | AT '(' parse_exp ')' phdr_info
+ {
+ $$ = $5;
+ $$.load_address = $3;
+ }