parser grammar GnuLdParser; options { tokenVocab = GnuLdLexer; } /* TODO: check right associative annotations */ /* %token INT %token NAME LNAME */ /* %right UNARY %token END %left LPAREN */ 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 ; filename: NAME; defsym_expr: // { ldlex_defsym(); } NAME EQ exp // { // ldlex_popstate(); // lang_add_assignment (exp_defsym ($2, $4)); // } ; /* SYNTAX WITHIN AN MRI SCRIPT FILE */ mri_script_file: // { // ldlex_mri_script (); // PUSH_ERROR (_("MRI style script")); // } mri_script_lines // { // ldlex_popstate (); // mri_draw_tree (); // POP_ERROR (); // } ; mri_script_lines: mri_script_lines mri_script_command NEWLINE | ; mri_script_command: CHIP exp | CHIP exp COMMA exp | NAME /*{ einfo(_("%P%F: unrecognised keyword in MRI style script '%s'\n"),$1); }*/ | LIST /*{ config.map_filename = "-"; }*/ | ORDER ordernamelist | ENDWORD | PUBLIC NAME EQ exp // { mri_public($2, $4); } | PUBLIC NAME COMMA exp // { mri_public($2, $4); } | PUBLIC NAME exp // { mri_public($2, $3); } | FORMAT NAME // { mri_format($2); } | SECT NAME COMMA exp // { mri_output_section($2, $4);} | SECT NAME exp // { mri_output_section($2, $3);} | SECT NAME EQ exp // { mri_output_section($2, $4);} | ALIGN_K NAME EQ exp // { mri_align($2,$4); } | ALIGN_K NAME COMMA exp // { mri_align($2,$4); } | ALIGNMOD NAME EQ exp // { mri_alignmod($2,$4); } | ALIGNMOD NAME COMMA exp // { mri_alignmod($2,$4); } | ABSOLUTE mri_abs_name_list | LOAD mri_load_name_list | NAMEWORD NAME // { mri_name($2); } | ALIAS NAME COMMA NAME // { mri_alias($2,$4,0);} | ALIAS NAME COMMA INT // { mri_alias ($2, 0, (int) $4.integer); } | BASE exp // { mri_base($2); } | TRUNCATE INT // { mri_truncate ((unsigned int) $2.integer); } | CASE casesymlist | EXTERN extern_name_list | INCLUDE filename // { ldlex_script (); ldfile_open_command_file($2); } mri_script_lines END // { ldlex_popstate (); } | START NAME // { lang_add_entry ($2, FALSE); } | ; ordernamelist: ordernamelist COMMA NAME // { mri_order($3); } | ordernamelist NAME // { mri_order($2); } | ; mri_load_name_list: NAME // { mri_load($1); } | mri_load_name_list COMMA NAME // { mri_load($3); } ; mri_abs_name_list: NAME // { mri_only_load($1); } | mri_abs_name_list COMMA NAME // { mri_only_load($3); } ; casesymlist: /* empty */ // { $$ = NULL; } | NAME | casesymlist COMMA 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, FALSE); } | extern_name_list_body NAME // { ldlang_add_undef ($2, FALSE); } | extern_name_list_body COMMA NAME // { ldlang_add_undef ($3, FALSE); } ; script_file: // { ldlex_both(); } ifile_list // { ldlex_popstate(); } ; ifile_list: ifile_list ifile_p1 | ; ifile_p1: memory | sections | phdrs | startup | high_level_library | low_level_library | floating_point_support | statement_anywhere | version | SEMICOLON | TARGET_K LPAREN NAME RPAREN // { lang_add_target($3); } | SEARCH_DIR LPAREN filename RPAREN // { ldfile_add_library_path ($3, FALSE); } | OUTPUT LPAREN filename RPAREN // { lang_add_output($3, 1); } | OUTPUT_FORMAT LPAREN NAME RPAREN // { lang_add_output_format ($3, (char *) NULL, // (char *) NULL, 1); } | OUTPUT_FORMAT LPAREN NAME COMMA NAME COMMA NAME RPAREN // { lang_add_output_format ($3, $5, $7, 1); } | OUTPUT_ARCH LPAREN NAME RPAREN // { ldfile_set_output_arch ($3, bfd_arch_unknown); } | FORCE_COMMON_ALLOCATION // { command_line.force_common_definition = TRUE ; } | INHIBIT_COMMON_ALLOCATION // { command_line.inhibit_common_definition = TRUE ; } | INPUT LPAREN input_list RPAREN | GROUP // { lang_enter_group (); } LPAREN input_list RPAREN // { lang_leave_group (); } | MAP LPAREN filename RPAREN // { lang_add_map($3); } | INCLUDE filename // { ldlex_script (); ldfile_open_command_file($2); } ifile_list END // { ldlex_popstate (); } | NOCROSSREFS LPAREN nocrossref_list RPAREN // { // lang_add_nocrossref ($3); // } | NOCROSSREFS_TO LPAREN nocrossref_list RPAREN // { // lang_add_nocrossref_to ($3); // } | EXTERN LPAREN extern_name_list RPAREN | INSERT_K AFTER NAME // { lang_add_insert ($3, 0); } | INSERT_K BEFORE NAME // { lang_add_insert ($3, 1); } | REGION_ALIAS LPAREN NAME COMMA NAME RPAREN // { lang_memory_region_alias ($3, $5); } | LD_FEATURE LPAREN NAME RPAREN // { lang_ld_feature ($3); } ; input_list: // { ldlex_inputlist(); } input_list1 // { ldlex_popstate(); } ; input_list1: NAME // { lang_add_input_file($1,lang_input_file_is_search_file_enum, // (char *)NULL); } | input_list1 COMMA NAME // { lang_add_input_file($3,lang_input_file_is_search_file_enum, // (char *)NULL); } | input_list1 NAME // { lang_add_input_file($2,lang_input_file_is_search_file_enum, // (char *)NULL); } | LNAME // { lang_add_input_file($1,lang_input_file_is_l_enum, // (char *)NULL); } | input_list1 COMMA LNAME // { lang_add_input_file($3,lang_input_file_is_l_enum, // (char *)NULL); } | input_list1 LNAME // { lang_add_input_file($2,lang_input_file_is_l_enum, // (char *)NULL); } | AS_NEEDED LPAREN // { $$ = input_flags.add_DT_NEEDED_for_regular; // input_flags.add_DT_NEEDED_for_regular = TRUE; } // input_list1 RPAREN // { input_flags.add_DT_NEEDED_for_regular = $3; } | input_list1 COMMA AS_NEEDED LPAREN // { $$ = input_flags.add_DT_NEEDED_for_regular; // input_flags.add_DT_NEEDED_for_regular = TRUE; } // input_list1 RPAREN // { input_flags.add_DT_NEEDED_for_regular = $5; } | input_list1 AS_NEEDED LPAREN // { $$ = input_flags.add_DT_NEEDED_for_regular; // input_flags.add_DT_NEEDED_for_regular = TRUE; } // input_list1 RPAREN // { input_flags.add_DT_NEEDED_for_regular = $4; } ; sections: SECTIONS LBRACE sec_or_group_p1 RBRACE ; sec_or_group_p1: sec_or_group_p1 section | sec_or_group_p1 statement_anywhere | ; statement_anywhere: ENTRY LPAREN NAME RPAREN // { lang_add_entry ($3, FALSE); } | assignment end | ASSERT_K /*{ldlex_expression ();}*/ LPAREN exp COMMA string RPAREN // { ldlex_popstate (); // lang_add_assignment (exp_assert ($4, $6)); } ; /* The '*' and '?' cases are there because the lexer returns them as separate tokens rather than as name. */ wildcard_name: NAME // { // $$ = $1; // } | STAR // { // $$ = "*"; // } | QUESTION // { // $$ = "?"; // } ; wildcard_spec: wildcard_name // { // $$.name = $1; // $$.sorted = none; // $$.exclude_name_list = NULL; // $$.section_flag_list = NULL; // } | EXCLUDE_FILE LPAREN exclude_name_list RPAREN wildcard_name // { // $$.name = $5; // $$.sorted = none; // $$.exclude_name_list = $3; // $$.section_flag_list = NULL; // } | SORT_BY_NAME LPAREN wildcard_name RPAREN // { // $$.name = $3; // $$.sorted = by_name; // $$.exclude_name_list = NULL; // $$.section_flag_list = NULL; // } | SORT_BY_ALIGNMENT LPAREN wildcard_name RPAREN // { // $$.name = $3; // $$.sorted = by_alignment; // $$.exclude_name_list = NULL; // $$.section_flag_list = NULL; // } | SORT_NONE LPAREN wildcard_name RPAREN // { // $$.name = $3; // $$.sorted = by_none; // $$.exclude_name_list = NULL; // $$.section_flag_list = NULL; // } | SORT_BY_NAME LPAREN SORT_BY_ALIGNMENT LPAREN wildcard_name RPAREN RPAREN // { // $$.name = $5; // $$.sorted = by_name_alignment; // $$.exclude_name_list = NULL; // $$.section_flag_list = NULL; // } | SORT_BY_NAME LPAREN SORT_BY_NAME LPAREN wildcard_name RPAREN RPAREN // { // $$.name = $5; // $$.sorted = by_name; // $$.exclude_name_list = NULL; // $$.section_flag_list = NULL; // } | SORT_BY_ALIGNMENT LPAREN SORT_BY_NAME LPAREN wildcard_name RPAREN RPAREN // { // $$.name = $5; // $$.sorted = by_alignment_name; // $$.exclude_name_list = NULL; // $$.section_flag_list = NULL; // } | SORT_BY_ALIGNMENT LPAREN SORT_BY_ALIGNMENT LPAREN wildcard_name RPAREN RPAREN // { // $$.name = $5; // $$.sorted = by_alignment; // $$.exclude_name_list = NULL; // $$.section_flag_list = NULL; // } | SORT_BY_NAME LPAREN EXCLUDE_FILE LPAREN exclude_name_list RPAREN wildcard_name RPAREN // { // $$.name = $7; // $$.sorted = by_name; // $$.exclude_name_list = $5; // $$.section_flag_list = NULL; // } | SORT_BY_INIT_PRIORITY LPAREN wildcard_name RPAREN // { // $$.name = $3; // $$.sorted = by_init_priority; // $$.exclude_name_list = NULL; // $$.section_flag_list = NULL; // } ; sect_flag_list: NAME // { // struct flag_info_list *n; // n = ((struct flag_info_list *) xmalloc (sizeof *n)); // if ($1[0] == '!') // { // n->with = without_flags; // n->name = &$1[1]; // } // else // { // n->with = with_flags; // n->name = $1; // } // n->valid = FALSE; // n->next = NULL; // $$ = n; // } | sect_flag_list AMPERSAND NAME // { // struct flag_info_list *n; // n = ((struct flag_info_list *) xmalloc (sizeof *n)); // if ($3[0] == '!') // { // n->with = without_flags; // n->name = &$3[1]; // } // else // { // n->with = with_flags; // n->name = $3; // } // n->valid = FALSE; // n->next = $1; // $$ = n; // } ; sect_flags: /*not used by antlr: INPUT_SECTION_FLAGS*/ LPAREN sect_flag_list RPAREN // { // struct flag_info *n; // n = ((struct flag_info *) xmalloc (sizeof *n)); // n->flag_list = $3; // n->flags_initialized = FALSE; // n->not_with_flags = 0; // n->only_with_flags = 0; // $$ = n; // } ; exclude_name_list: exclude_name_list wildcard_name // { // struct name_list *tmp; // tmp = (struct name_list *) xmalloc (sizeof *tmp); // tmp->name = $2; // tmp->next = $1; // $$ = tmp; // } | wildcard_name // { // struct name_list *tmp; // tmp = (struct name_list *) xmalloc (sizeof *tmp); // tmp->name = $1; // tmp->next = NULL; // $$ = tmp; // } ; file_name_list: file_name_list opt_comma wildcard_spec // { // struct wildcard_list *tmp; // tmp = (struct wildcard_list *) xmalloc (sizeof *tmp); // tmp->next = $1; // tmp->spec = $3; // $$ = tmp; // } | wildcard_spec // { // struct wildcard_list *tmp; // tmp = (struct wildcard_list *) xmalloc (sizeof *tmp); // tmp->next = NULL; // tmp->spec = $1; // $$ = tmp; // } ; input_section_spec_no_keep: NAME // { // struct wildcard_spec tmp; // tmp.name = $1; // tmp.exclude_name_list = NULL; // tmp.sorted = none; // tmp.section_flag_list = NULL; // lang_add_wild (&tmp, NULL, ldgram_had_keep); // } | sect_flags NAME // { // struct wildcard_spec tmp; // tmp.name = $2; // tmp.exclude_name_list = NULL; // tmp.sorted = none; // tmp.section_flag_list = $1; // lang_add_wild (&tmp, NULL, ldgram_had_keep); // } | LBRACKET file_name_list RBRACKET // { // lang_add_wild (NULL, $2, ldgram_had_keep); // } | sect_flags LBRACKET file_name_list RBRACKET // { // struct wildcard_spec tmp; // tmp.name = NULL; // tmp.exclude_name_list = NULL; // tmp.sorted = none; // tmp.section_flag_list = $1; // lang_add_wild (&tmp, $3, ldgram_had_keep); // } | wildcard_spec LPAREN file_name_list RPAREN // { // lang_add_wild (&$1, $3, ldgram_had_keep); // } | sect_flags wildcard_spec LPAREN file_name_list RPAREN // { // $2.section_flag_list = $1; // lang_add_wild (&$2, $4, ldgram_had_keep); // } ; input_section_spec: input_section_spec_no_keep | KEEP LPAREN // { ldgram_had_keep = TRUE; } input_section_spec_no_keep RPAREN // { ldgram_had_keep = FALSE; } ; statement: assignment end | CREATE_OBJECT_SYMBOLS // { // lang_add_attribute(lang_object_symbols_statement_enum); // } | SEMICOLON | CONSTRUCTORS // { // // lang_add_attribute(lang_constructors_statement_enum); // } | SORT_BY_NAME LPAREN CONSTRUCTORS RPAREN // { // constructors_sorted = TRUE; // lang_add_attribute (lang_constructors_statement_enum); // } | input_section_spec | length LPAREN mustbe_exp RPAREN // { // lang_add_data ((int) $1, $3); // } | FILL LPAREN fill_exp RPAREN // { // lang_add_fill ($3); // } | ASSERT_K /*{ldlex_expression ();}*/ LPAREN exp COMMA NAME RPAREN end // { ldlex_popstate (); // lang_add_assignment (exp_assert ($4, $6)); } | INCLUDE filename // { ldlex_script (); ldfile_open_command_file($2); } statement_list_opt END // { ldlex_popstate (); } ; statement_list: statement_list statement | statement ; statement_list_opt: /* empty */ | statement_list ; length: QUAD // { $$ = $1; } | SQUAD // { $$ = $1; } | LONG // { $$ = $1; } | SHORT // { $$ = $1; } | BYTE // { $$ = $1; } ; fill_exp: mustbe_exp // { // $$ = exp_get_fill ($1, 0, "fill value"); // } ; fill_opt: EQ fill_exp // { $$ = $2; } | // { $$ = (fill_type *) 0; } ; assign_op: PLUSEQ // { $$ = '+'; } | MINUSEQ // { $$ = '-'; } | MULTEQ // { $$ = '*'; } | DIVEQ // { $$ = '/'; } | LSHIFTEQ // { $$ = LSHIFT; } | RSHIFTEQ // { $$ = RSHIFT; } | ANDEQ // { $$ = '&'; } | OREQ // { $$ = '|'; } ; end: SEMICOLON | COMMA ; assignment: NAME EQ mustbe_exp // { // lang_add_assignment (exp_assign ($1, $3, FALSE)); // } | NAME assign_op mustbe_exp // { // lang_add_assignment (exp_assign ($1, // exp_binop ($2, // exp_nameop (NAME, // $1), // $3), FALSE)); // } | HIDDEN_ LPAREN NAME EQ mustbe_exp RPAREN // { // lang_add_assignment (exp_assign ($3, $5, TRUE)); // } | PROVIDE LPAREN NAME EQ mustbe_exp RPAREN // { // lang_add_assignment (exp_provide ($3, $5, FALSE)); // } | PROVIDE_HIDDEN LPAREN NAME EQ mustbe_exp RPAREN // { // lang_add_assignment (exp_provide ($3, $5, TRUE)); // } ; opt_comma: COMMA | ; memory: MEMORY LBRACE memory_spec_list_opt RBRACE ; memory_spec_list_opt: memory_spec_list | ; memory_spec_list: memory_spec_list opt_comma memory_spec | memory_spec ; memory_spec: NAME // { region = lang_memory_region_lookup ($1, TRUE); } attributes_opt COLON origin_spec opt_comma length_spec // {} | INCLUDE filename // { ldlex_script (); ldfile_open_command_file($2); } memory_spec_list_opt END // { ldlex_popstate (); } ; origin_spec: ORIGIN EQ mustbe_exp // { // region->origin_exp = $3; // region->current = region->origin; // } ; length_spec: LENGTH EQ mustbe_exp // { // region->length_exp = $3; // } ; attributes_opt: /* empty */ /* { *//* dummy action to avoid bison 1.25 error message *//* } |*/ LPAREN attributes_list RPAREN ; attributes_list: attributes_string | attributes_list attributes_string ; attributes_string: NAME # attributeNormal // { lang_set_flags (region, $1, 0); } | EXLAMATION NAME # attributeInverted // { lang_set_flags (region, $2, 1); } ; /* This would be best but the tokenizer would have to be made context sensitive which is too much work given how easy it is to check the flags after parsing. attributes_string : attribute | '!' attribute # attributeInverted ; attribute: 'r' | 'w' | 'x' | 'a' | 'i' | 'l' ; */ startup: STARTUP LPAREN filename RPAREN // { lang_startup($3); } ; high_level_library: HLL LPAREN high_level_library_NAME_list RPAREN | HLL LPAREN RPAREN // { ldemul_hll((char *)NULL); } ; high_level_library_NAME_list: high_level_library_NAME_list opt_comma filename // { ldemul_hll($3); } | filename // { ldemul_hll($1); } ; low_level_library: SYSLIB LPAREN low_level_library_NAME_list RPAREN ; low_level_library_NAME_list: low_level_library_NAME_list opt_comma filename // { ldemul_syslib($3); } | ; floating_point_support: FLOAT // { lang_float(TRUE); } | NOFLOAT // { lang_float(FALSE); } ; nocrossref_list: /* empty */ // { // $$ = NULL; // } | NAME nocrossref_list // { // struct lang_nocrossref *n; // // n = (struct lang_nocrossref *) xmalloc (sizeof *n); // n->name = $1; // n->next = $2; // $$ = n; // } | NAME COMMA nocrossref_list // { // struct lang_nocrossref *n; // // n = (struct lang_nocrossref *) xmalloc (sizeof *n); // n->name = $1; // n->next = $3; // $$ = n; // } ; mustbe_exp: // { ldlex_expression (); } exp // { ldlex_popstate (); $$=$2;} ; exp : DASH exp # expNegate // TODO: %prec UNARY // { $$ = exp_unop ('-', $2); } | LPAREN exp RPAREN # expParen // { $$ = $2; } | NEXT LPAREN exp RPAREN # expNextParen // TODO: %prec UNARY // { $$ = exp_unop ((int) $1,$3); } | EXLAMATION exp # expInvert // TODO: %prec UNARY // { $$ = exp_unop ('!', $2); } | PLUS exp # expPlus // TODO: %prec UNARY // { $$ = $2; } | TILDE exp # expMinus // TODO: %prec UNARY // { $$ = exp_unop ('~', $2);} | exp STAR exp # expMul // { $$ = exp_binop ('*', $1, $3); } | exp SLASH exp # expDiv // { $$ = exp_binop ('/', $1, $3); } | exp MOD exp # expMod // { $$ = exp_binop ('%', $1, $3); } | exp PLUS exp # expAdd // { $$ = exp_binop ('+', $1, $3); } | exp DASH exp # expSub // { $$ = exp_binop ('-' , $1, $3); } | exp LSHIFT exp # expLshift // { $$ = exp_binop (LSHIFT , $1, $3); } | exp RSHIFT exp # expRshift // { $$ = exp_binop (RSHIFT , $1, $3); } | exp EQEQ exp # expEq // { $$ = exp_binop (EQ , $1, $3); } | exp NE exp # expNe // { $$ = exp_binop (NE , $1, $3); } | exp LE exp # expLe // { $$ = exp_binop (LE , $1, $3); } | exp GE exp # expGe // { $$ = exp_binop (GE , $1, $3); } | exp LT exp # expLt // { $$ = exp_binop ('<' , $1, $3); } | exp GT exp # expGt // { $$ = exp_binop ('>' , $1, $3); } | exp AMPERSAND exp # expAnd // { $$ = exp_binop ('&' , $1, $3); } | exp HAT exp # expXor // { $$ = exp_binop ('^' , $1, $3); } | exp BAR exp # expOr // { $$ = exp_binop ('|' , $1, $3); } | exp QUESTION exp COLON exp # expTrinary // { $$ = exp_trinop ('?' , $1, $3, $5); } | exp ANDAND exp # expAndand // { $$ = exp_binop (ANDAND , $1, $3); } | exp OROR exp # expOror // { $$ = exp_binop (OROR , $1, $3); } | DEFINED LPAREN NAME RPAREN # expDefined // { $$ = exp_nameop (DEFINED, $3); } | INT # expInt // { $$ = exp_bigintop ($1.integer, $1.str); } | SIZEOF_HEADERS # expSizeofHeaders // { $$ = exp_nameop (SIZEOF_HEADERS,0); } | ALIGNOF LPAREN NAME RPAREN # expAlignof // { $$ = exp_nameop (ALIGNOF,$3); } | SIZEOF LPAREN NAME RPAREN # expSizeof // { $$ = exp_nameop (SIZEOF,$3); } | ADDR LPAREN NAME RPAREN # expAddr // { $$ = exp_nameop (ADDR,$3); } | LOADADDR LPAREN NAME RPAREN # expLoadaddr // { $$ = exp_nameop (LOADADDR,$3); } | CONSTANT LPAREN NAME RPAREN # expConstant // { $$ = exp_nameop (CONSTANT,$3); } | ABSOLUTE LPAREN exp RPAREN # expAbsolute // { $$ = exp_unop (ABSOLUTE, $3); } | ALIGN_K LPAREN exp RPAREN # expAlign // { $$ = exp_unop (ALIGN_K,$3); } | ALIGN_K LPAREN exp COMMA exp RPAREN # expAlignK // { $$ = exp_binop (ALIGN_K,$3,$5); } | DATA_SEGMENT_ALIGN LPAREN exp COMMA exp RPAREN # expDataSegmentAlign // { $$ = exp_binop (DATA_SEGMENT_ALIGN, $3, $5); } | DATA_SEGMENT_RELRO_END LPAREN exp COMMA exp RPAREN # expDataSegmentRelRoEnd // { $$ = exp_binop (DATA_SEGMENT_RELRO_END, $5, $3); | DATA_SEGMENT_END LPAREN exp RPAREN # expDataSegmentEnd // { $$ = exp_unop (DATA_SEGMENT_END, $3); } | SEGMENT_START LPAREN NAME COMMA exp RPAREN # expSegmentStart // { /* The operands to the expression node are // placed in the opposite order from the way // in which they appear in the script as // that allows us to reuse more code in // fold_binary. */ // $$ = exp_binop (SEGMENT_START, // $5, // exp_nameop (NAME, $3)); } | BLOCK LPAREN exp RPAREN # expBlock // { $$ = exp_unop (ALIGN_K,$3); } | NAME # expName // { $$ = exp_nameop (NAME,$1); } | MAX_K LPAREN exp COMMA exp RPAREN # expMax // { $$ = exp_binop (MAX_K, $3, $5 ); } | MIN_K LPAREN exp COMMA exp RPAREN # expMin // { $$ = exp_binop (MIN_K, $3, $5 ); } | ASSERT_K LPAREN exp COMMA NAME RPAREN # expAssert // { $$ = exp_assert ($3, $5); } | ORIGIN LPAREN NAME RPAREN # expOrigin // { $$ = exp_nameop (ORIGIN, $3); } | LENGTH LPAREN NAME RPAREN # expLengthExp // { $$ = exp_nameop (LENGTH, $3); } | LOG2CEIL LPAREN exp RPAREN # expLog2ceil // { $$ = exp_unop (LOG2CEIL, $3); } ; memspec_at_opt: AT GT NAME // { $$ = $3; } | // { $$ = 0; } ; opt_at: AT LPAREN exp RPAREN // { $$ = $3; } | // { $$ = 0; } ; opt_align: ALIGN_K LPAREN exp RPAREN // { $$ = $3; } | // { $$ = 0; } ; opt_align_with_input: ALIGN_WITH_INPUT // { $$ = ALIGN_WITH_INPUT; } | // { $$ = 0; } ; opt_subalign: SUBALIGN LPAREN exp RPAREN // { $$ = $3; } | // { $$ = 0; } ; 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_align_with_input opt_subalign // { ldlex_popstate (); ldlex_script (); } sect_constraint LBRACE // { // lang_enter_output_section_statement($1, $3, // sectype, // $5, $7, $4, $9, $6); // } statement_list_opt RBRACE // { ldlex_popstate (); ldlex_expression (); } memspec_opt memspec_at_opt phdr_opt fill_opt // { // ldlex_popstate (); // lang_leave_output_section_statement ($18, $15, $17, $16); // } opt_comma {} | OVERLAY // { ldlex_expression (); } opt_exp_without_type opt_nocrossrefs opt_at opt_subalign // { ldlex_popstate (); ldlex_script (); } LBRACE // { // lang_enter_overlay ($3, $6); // } overlay_section RBRACE // { ldlex_popstate (); ldlex_expression (); } memspec_opt memspec_at_opt phdr_opt fill_opt // { // ldlex_popstate (); // lang_leave_overlay ($5, (int) $4, // $16, $13, $15, $14); // } opt_comma | /* The GROUP case is just enough to support the gcc svr3.ifile script. It is not intended to be full support. I'm not even sure what GROUP is supposed to mean. */ GROUP // { ldlex_expression (); } opt_exp_with_type // { // ldlex_popstate (); // lang_add_assignment (exp_assign (".", $3, FALSE)); // } LBRACE sec_or_group_p1 RBRACE | INCLUDE filename // { ldlex_script (); ldfile_open_command_file($2); } sec_or_group_p1 END // { ldlex_popstate (); } ; type: NOLOAD // { sectype = noload_section; } | DSECT // { sectype = noalloc_section; } | COPY // { sectype = noalloc_section; } | INFO // { sectype = noalloc_section; } | OVERLAY // { sectype = noalloc_section; } ; atype: LPAREN type RPAREN | /* EMPTY */ // { sectype = normal_section; } | LPAREN RPAREN // { sectype = normal_section; } ; opt_exp_with_type: exp atype COLON // { $$ = $1; } | atype COLON // { $$ = (etree_type *)NULL; } | /* The BIND cases are to support the gcc svr3.ifile script. They aren't intended to implement full support for the BIND keyword. I'm not even sure what BIND is supposed to mean. */ BIND LPAREN exp RPAREN atype COLON // { $$ = $3; } | BIND LPAREN exp RPAREN BLOCK LPAREN exp RPAREN atype COLON // { $$ = $3; } ; opt_exp_without_type: exp COLON // { $$ = $1; } | COLON // { $$ = (etree_type *) NULL; } ; opt_nocrossrefs: /* empty */ // { $$ = 0; } | NOCROSSREFS // { $$ = 1; } ; memspec_opt: GT NAME // { $$ = $2; } | // { $$ = DEFAULT_MEMORY_REGION; } ; phdr_opt: /* empty */ // { // $$ = NULL; // } | phdr_opt COLON NAME // { // struct lang_output_section_phdr_list *n; // // n = ((struct lang_output_section_phdr_list *) // xmalloc (sizeof *n)); // n->name = $3; // n->used = FALSE; // n->next = $1; // $$ = n; // } ; overlay_section: /* empty */ | overlay_section NAME // { // ldlex_script (); // lang_enter_overlay_section ($2); // } LBRACE statement_list_opt RBRACE // { ldlex_popstate (); ldlex_expression (); } phdr_opt fill_opt // { // ldlex_popstate (); // lang_leave_overlay_section ($9, $8); // } opt_comma ; phdrs: PHDRS LBRACE phdr_list RBRACE ; phdr_list: /* empty */ | phdr_list phdr ; phdr: NAME // { ldlex_expression (); } phdr_type phdr_qualifiers // { ldlex_popstate (); } SEMICOLON // { // lang_new_phdr ($1, $3, $4.filehdr, $4.phdrs, $4.at, // $4.flags); // } ; phdr_type: exp // { // $$ = $1; // // if ($1->type.node_class == etree_name // && $1->type.node_code ==name) // { // const char *s; // unsigned int i; // static const char * const phdr_types[] = // { // "PT_NULL", "PT_LOAD", "PT_DYNAMIC", // "PT_INTERP", "PT_NOTE", "PT_SHLIB", // "PT_PHDR", "PT_TLS" // }; // // s = $1->name.name; // for (i = 0; // i < sizeof phdr_types / sizeof phdr_types[0]; // i++) // if (strcmp (s, phdr_types[i]) == 0) // { // $$ = exp_intop (i); // break; // } // if (i == sizeof phdr_types / sizeof phdr_types[0]) // { // if (strcmp (s, "PT_GNU_EH_FRAME") == 0) // $$ = exp_intop (0x6474e550); // else if (strcmp (s, "PT_GNU_STACK") == 0) // $$ = exp_intop (0x6474e551); // else // { // einfo (_("\ //%X%P:%S: unknown phdr type `%s' (try integer literal)\n"), // NULL, s); // $$ = exp_intop (0); // } // } // } // } ; phdr_qualifiers: /* empty */ // { // memset (&$$, 0, sizeof (struct phdr_info)); // } | NAME phdr_val phdr_qualifiers // { // $$ = $3; // if (strcmp ($1, "FILEHDR") == 0 && $2 == NULL) // $$.filehdr = TRUE; // else if (strcmp ($1, "PHDRS") == 0 && $2 == NULL) // $$.phdrs = TRUE; // else if (strcmp ($1, "FLAGS") == 0 && $2 != NULL) // $$.flags = $2; // else // einfo (_("%X%P:%S: PHDRS syntax error at `%s'\n"), // NULL, $1); // } | AT LPAREN exp RPAREN phdr_qualifiers // { // $$ = $5; // $$.at = $3; // } ; phdr_val: /* empty */ // { // $$ = NULL; // } | LPAREN exp RPAREN // { // $$ = $2; // } ; 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: LBRACE dynamic_list_tag RBRACE SEMICOLON ; dynamic_list_tag: vers_defns SEMICOLON // { // lang_append_dynamic_list ($1); // } ; /* This syntax is used within an external version script file. */ version_script_file: // { // ldlex_version_file (); // PUSH_ERROR (_("VERSION script")); // } vers_nodes // { // ldlex_popstate (); // POP_ERROR (); // } ; /* This is used within a normal linker script file. */ version: // { // ldlex_version_script (); // } VERSIONK LBRACE vers_nodes RBRACE // { // ldlex_popstate (); // } ; vers_nodes: vers_node | vers_nodes vers_node ; vers_node: LBRACE vers_tag RBRACE SEMICOLON // { // lang_register_vers_node (NULL, $2, NULL); // } | VERS_TAG LBRACE vers_tag RBRACE SEMICOLON // { // lang_register_vers_node ($1, $3, NULL); // } | VERS_TAG LBRACE vers_tag RBRACE verdep SEMICOLON // { // lang_register_vers_node ($1, $3, $5); // } ; verdep: VERS_TAG // { // $$ = lang_add_vers_depend (NULL, $1); // } | verdep VERS_TAG // { // $$ = lang_add_vers_depend ($1, $2); // } ; vers_tag: /* empty */ // { // $$ = lang_new_vers_node (NULL, NULL); // } | vers_defns SEMICOLON // { // $$ = lang_new_vers_node ($1, NULL); // } | GLOBAL COLON vers_defns SEMICOLON // { // $$ = lang_new_vers_node ($3, NULL); // } | LOCAL COLON vers_defns SEMICOLON // { // $$ = lang_new_vers_node (NULL, $3); // } | GLOBAL COLON vers_defns SEMICOLON LOCAL COLON vers_defns SEMICOLON // { // $$ = lang_new_vers_node ($3, $7); // } ; vers_defns: VERS_IDENTIFIER // { // $$ = 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 SEMICOLON VERS_IDENTIFIER // { // $$ = lang_new_vers_pattern ($1, $3, ldgram_vers_current_lang, FALSE); // } | vers_defns SEMICOLON NAME // { // $$ = lang_new_vers_pattern ($1, $3, ldgram_vers_current_lang, TRUE); // } | vers_defns SEMICOLON EXTERN NAME LBRACE // { // $$ = ldgram_vers_current_lang; // ldgram_vers_current_lang = $4; // } vers_defns opt_semicolon RBRACE // { // struct bfd_elf_version_expr *pat; // for (pat = $7; pat->next != NULL; pat = pat->next); // pat->next = $1; // $$ = $7; // ldgram_vers_current_lang = $6; // } | EXTERN NAME LBRACE // { // $$ = ldgram_vers_current_lang; // ldgram_vers_current_lang = $2; // } vers_defns opt_semicolon RBRACE // { // $$ = $5; // ldgram_vers_current_lang = $4; // } | GLOBAL // { // $$ = lang_new_vers_pattern (NULL, "global", ldgram_vers_current_lang, FALSE); // } | vers_defns SEMICOLON 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 SEMICOLON 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 SEMICOLON EXTERN // { // $$ = lang_new_vers_pattern ($1, "extern", ldgram_vers_current_lang, FALSE); // } ; opt_semicolon: /* empty */ | SEMICOLON ; //name // : NAME; string: STRING_ANY*;