X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=ld%2Fldgram.y;h=7e6f1e8e0b1dbda640602f57b6b95995b04b9cec;hb=501be095c99cb8b8e83176861f4d647f1247531b;hp=ce0f4a133e0b4e9c85c93f4e6a03430e0e35c95a;hpb=76971f0da2260c069b0ae13740627dba1b39487b;p=deliverable%2Fbinutils-gdb.git diff --git a/ld/ldgram.y b/ld/ldgram.y index ce0f4a133e..7e6f1e8e0b 100644 --- a/ld/ldgram.y +++ b/ld/ldgram.y @@ -1,5 +1,5 @@ /* A YACC grammer to parse a superset of the AT&T linker scripting languaue. - Copyright (C) 1991 Free Software Foundation, Inc. + Copyright (C) 1991, 1993 Free Software Foundation, Inc. Written by Steve Chamberlain of Cygnus Support (steve@cygnus.com). This file is part of GNU ld. @@ -16,7 +16,7 @@ GNU General Public License for more details. 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ %{ /* @@ -27,6 +27,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "bfd.h" #include "sysdep.h" +#include "bfdlink.h" #include "ld.h" #include "ldexp.h" #include "ldver.h" @@ -34,40 +35,19 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "ldemul.h" #include "ldfile.h" #include "ldmisc.h" +#include "ldmain.h" +#include "mri.h" +#include "ldlex.h" - +#ifndef YYDEBUG #define YYDEBUG 1 +#endif -boolean option_v; -extern unsigned int lineno; -extern boolean trace_files; -extern boolean write_map; -extern boolean option_longmap; -boolean hex_mode; - -strip_symbols_type strip_symbols=STRIP_NONE; -discard_locals_type discard_locals=DISCARD_NONE; - +static int typebits; lang_memory_region_type *region; -lang_memory_region_type *lang_memory_region_lookup(); -lang_output_section_statement_type *lang_output_section_statement_lookup(); - -#ifdef __STDC__ - -void lang_add_data(int type, union etree_union *exp); -void lang_enter_output_section_statement(char *output_section_statement_name, etree_type *address_exp, int flags, bfd_vma block_value); - -#else - -void lang_add_data(); -void lang_enter_output_section_statement(); - -#endif /* __STDC__ */ - -extern args_type command_line; char *current_file; boolean ldgram_want_filename = true; boolean had_script = false; @@ -75,36 +55,26 @@ boolean force_make_executable = false; boolean ldgram_in_script = false; boolean ldgram_had_equals = false; -/* LOCALS */ - - +#define ERROR_NAME_MAX 20 +static char *error_names[ERROR_NAME_MAX]; +static int error_index; +#define PUSH_ERROR(x) if (error_index < ERROR_NAME_MAX) error_names[error_index] = x; error_index++; +#define POP_ERROR() error_index--; %} %union { bfd_vma integer; - int voidval; char *name; int token; union etree_union *etree; -struct sec *section; - struct lang_output_section_statement_struct *output_section_statement; - union lang_statement_union **statement_ptr; - int lineno; - struct { - FILE *file; - char *name; - unsigned int lineno; - } state; - - } -%type exp opt_exp -%type fill_opt opt_block opt_type -%type memspec_opt +%type exp opt_exp_with_type mustbe_exp opt_at +%type fill_opt +%type memspec_opt casesymlist %token INT -%token NAME +%token NAME LNAME %type length %right PLUSEQ MINUSEQ MULTEQ DIVEQ '=' LSHIFTEQ RSHIFTEQ ANDEQ OREQ @@ -121,231 +91,160 @@ struct sec *section; %left '+' '-' %left '*' '/' '%' -/*%token '+' '-' '*' '/' '%'*/ %right UNARY +%token END %left '(' -%token ALIGN_K BLOCK LONG SHORT BYTE -%token SECTIONS +%token ALIGN_K BLOCK QUAD LONG SHORT BYTE +%token SECTIONS %token '{' '}' %token SIZEOF_HEADERS OUTPUT_FORMAT FORCE_COMMON_ALLOCATION OUTPUT_ARCH %token SIZEOF_HEADERS -%token MEMORY +%token INCLUDE +%token MEMORY DEFSYMEND %token NOLOAD DSECT COPY INFO OVERLAY -%token NAME DEFINED TARGET_K SEARCH_DIR MAP ENTRY -%token OPTION_e OPTION_c OPTION_noinhibit_exec OPTION_s OPTION_S OPTION_sort_common -%token OPTION_format OPTION_F OPTION_u OPTION_Bstatic OPTION_N -%token SIZEOF NEXT ADDR -%token OPTION_d OPTION_dc OPTION_dp OPTION_x OPTION_X OPTION_defsym -%token OPTION_v OPTION_V OPTION_M OPTION_t STARTUP HLL SYSLIB FLOAT NOFLOAT -%token OPTION_Map -%token OPTION_n OPTION_r OPTION_o OPTION_b OPTION_R OPTION_relax -%token OPTION_l OPTION_L OPTION_T OPTION_Aarch OPTION_Tfile OPTION_Texp -%token OPTION_Ur -%token ORIGIN FILL OPTION_g -%token LENGTH CREATE_OBJECT_SYMBOLS INPUT OUTPUT CONSTRUCTORS +%token NAME LNAME DEFINED TARGET_K SEARCH_DIR MAP ENTRY +%token SIZEOF NEXT ADDR +%token STARTUP HLL SYSLIB FLOAT NOFLOAT +%token ORIGIN FILL +%token LENGTH CREATE_OBJECT_SYMBOLS INPUT GROUP OUTPUT CONSTRUCTORS +%token ALIGNMOD AT PROVIDE %type assign_op - %type filename - -%{ -ld_config_type config; -%} +%token CHIP LIST SECT ABSOLUTE LOAD NEWLINE ENDWORD ORDER NAMEWORD +%token FORMAT PUBLIC DEFSYMEND BASE ALIAS TRUNCATE REL +%token INPUT_SCRIPT INPUT_MRI_SCRIPT INPUT_DEFSYM CASE EXTERN START %% -file: command_line { lang_final(); }; +file: + INPUT_SCRIPT script_file + | INPUT_MRI_SCRIPT mri_script_file + | INPUT_DEFSYM defsym_expr + ; -filename: - NAME; +filename: NAME; -command_line: - command_line command_line_option - | - ; -command_line_option: - '{' - { ldgram_in_script = true; } - ifile_list - { ldgram_in_script = false; } - '}' - | OPTION_Bstatic { } - | OPTION_v - { - ldversion(0); - option_v = true; - } - | OPTION_V - { - ldversion(1); - option_v = true; - } - | OPTION_t { - trace_files = true; - } - | OPTION_Map NAME +defsym_expr: + { ldlex_defsym(); } + NAME '=' exp { - write_map = true; - config.map_filename = $2; + ldlex_popstate(); + lang_add_assignment(exp_assop($3,$2,$4)); } - | OPTION_M { - config.map_filename = "-"; - - } - | OPTION_n { - config.magic_demand_paged = false; - } - | OPTION_N { - config.text_read_only = false; - config.magic_demand_paged = false; - } - | OPTION_s { - strip_symbols = STRIP_ALL; - } - | OPTION_S { - strip_symbols = STRIP_DEBUGGER; - } - | OPTION_u NAME { - ldlang_add_undef($2); - } - - | OPTION_r { - config.relocateable_output = true; - config.build_constructors = false; - config.magic_demand_paged = false; - config.text_read_only = false; - } - | OPTION_Ur { - config.relocateable_output = true; - config.build_constructors = true; - config.magic_demand_paged = false; - config.text_read_only = false; - } - | OPTION_o filename - { - lang_add_output($2); - } - | OPTION_e NAME - { lang_add_entry($2); - } - | OPTION_X { - discard_locals = DISCARD_L; +/* SYNTAX WITHIN AN MRI SCRIPT FILE */ +mri_script_file: + { ldlex_mri_script(); + PUSH_ERROR("MRI style script"); } - | OPTION_x { - discard_locals = DISCARD_ALL; + mri_script_lines + { ldlex_popstate(); + POP_ERROR(); } + ; - | OPTION_noinhibit_exec - { - force_make_executable = true; - } - | OPTION_sort_common { - config.sort_common = true; - } - | OPTION_d { - command_line.force_common_definition = true; - } - - | OPTION_relax { - command_line.relax = true; - } - | OPTION_dc - { - command_line.force_common_definition = true; - } - | OPTION_g - { - /* Ignored */ - } - | OPTION_dp - { - command_line.force_common_definition = true; - } - | OPTION_format NAME - { - lang_add_target($2); - } - | OPTION_Texp - { - hex_mode =true; - } - INT - { - lang_section_start($1,exp_intop($3)); - hex_mode = false; - } - - | OPTION_Aarch - { - ldfile_add_arch($1); - } - | OPTION_b NAME - { - lang_add_target($2); - } - | OPTION_L - { - ldfile_add_library_path($1); - } - | OPTION_F - { - /* Ignore */ - } - | NAME - { lang_add_input_file($1,lang_input_file_is_file_enum, - (char *)NULL); } - | OPTION_c filename - { ldfile_open_command_file($2); } script_file - | OPTION_Tfile - { ldfile_open_command_file($1); } script_file - - | OPTION_T filename - { ldfile_open_command_file($2); } script_file +mri_script_lines: + mri_script_lines mri_script_command NEWLINE + | + ; - | OPTION_l - { - lang_add_input_file($1, - lang_input_file_is_l_enum, - (char *)NULL); +mri_script_command: + CHIP exp + | CHIP exp ',' exp + | NAME { + einfo("%P%F: unrecognised keyword in MRI style script '%s'\n",$1); } - | OPTION_R filename - { - lang_add_input_file($2, - lang_input_file_is_symbols_only_enum, - (char *)NULL); - } - | OPTION_defsym - { + | LIST { + config.map_filename = "-"; } - NAME '=' - exp - { - lang_add_assignment(exp_assop($4,$3,$5)); - } - | '-' NAME - { info("%P%F Unrecognised option -%s\n", $2); } - + | ORDER ordernamelist + | ENDWORD + | PUBLIC NAME '=' exp + { mri_public($2, $4); } + | PUBLIC NAME ',' exp + { mri_public($2, $4); } + | PUBLIC NAME exp + { mri_public($2, $3); } + | FORMAT NAME + { mri_format($2); } + | SECT NAME ',' exp + { mri_output_section($2, $4);} + | SECT NAME exp + { mri_output_section($2, $3);} + | SECT NAME '=' exp + { mri_output_section($2, $4);} + | ALIGN_K NAME '=' exp + { mri_align($2,$4); } + | ALIGNMOD NAME '=' exp + { mri_alignmod($2,$4); } + | ABSOLUTE mri_abs_name_list + | LOAD mri_load_name_list + | NAMEWORD NAME + { mri_name($2); } + | ALIAS NAME ',' NAME + { mri_alias($2,$4,0);} + | ALIAS NAME ',' INT + { mri_alias($2,0,(int) $4);} + | BASE exp + { mri_base($2); } + | TRUNCATE INT + { mri_truncate((unsigned int) $2); } + | CASE casesymlist + | EXTERN extern_name_list + | INCLUDE filename + { ldfile_open_command_file ($2); } mri_script_lines END + | START NAME + { lang_add_entry ($2, 0); } + | ; +ordernamelist: + ordernamelist ',' NAME { mri_order($3); } + | ordernamelist NAME { mri_order($2); } + | + ; - - +mri_load_name_list: + NAME + { mri_load($1); } + | mri_load_name_list ',' NAME { mri_load($3); } + ; +mri_abs_name_list: + NAME + { mri_only_load($1); } + | mri_abs_name_list ',' NAME + { mri_only_load($3); } + ; +casesymlist: + /* empty */ { $$ = NULL; } + | NAME + | casesymlist ',' NAME + ; +extern_name_list: + NAME + { ldlang_add_undef ($1); } + | extern_name_list ',' NAME + { ldlang_add_undef ($3); } + ; script_file: - { ldgram_in_script = true; } - ifile_list '}' - { ldgram_in_script = false; } - + { + ldlex_both(); + } + ifile_list + { + ldlex_popstate(); + } ; ifile_list: - ifile_list ifile_p1 + ifile_list ifile_p1 | ; @@ -359,57 +258,74 @@ ifile_p1: | low_level_library | floating_point_support | statement_anywhere - | ';' + | ';' | TARGET_K '(' NAME ')' { lang_add_target($3); } | SEARCH_DIR '(' filename ')' - { ldfile_add_library_path($3); } + { ldfile_add_library_path ($3, false); } | OUTPUT '(' filename ')' - { lang_add_output($3); } - | OUTPUT_FORMAT '(' NAME ')' - { lang_add_output_format($3); } - | OUTPUT_ARCH '(' NAME ')' + { lang_add_output($3, 1); } + | OUTPUT_FORMAT '(' NAME ')' + { lang_add_output_format ($3, (char *) NULL, + (char *) NULL, 1); } + | OUTPUT_FORMAT '(' NAME ',' NAME ',' NAME ')' + { lang_add_output_format ($3, $5, $7, 1); } + | OUTPUT_ARCH '(' NAME ')' { ldfile_set_output_arch($3); } | FORCE_COMMON_ALLOCATION { command_line.force_common_definition = true ; } | INPUT '(' input_list ')' + | GROUP + { lang_enter_group (); } + '(' input_list ')' + { lang_leave_group (); } | MAP '(' filename ')' { lang_add_map($3); } + | INCLUDE filename + { ldfile_open_command_file($2); } ifile_list END ; input_list: NAME - { lang_add_input_file($1,lang_input_file_is_file_enum, + { lang_add_input_file($1,lang_input_file_is_search_file_enum, (char *)NULL); } | input_list ',' NAME - { lang_add_input_file($3,lang_input_file_is_file_enum, + { lang_add_input_file($3,lang_input_file_is_search_file_enum, + (char *)NULL); } + | input_list 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_list NAME - { lang_add_input_file($2, lang_input_file_is_file_enum, + | input_list ',' LNAME + { lang_add_input_file($3,lang_input_file_is_l_enum, + (char *)NULL); } + | input_list LNAME + { lang_add_input_file($2,lang_input_file_is_l_enum, (char *)NULL); } ; sections: - SECTIONS '{'sec_or_group_p1 '}' + SECTIONS '{' sec_or_group_p1 '}' ; sec_or_group_p1: sec_or_group_p1 section | sec_or_group_p1 statement_anywhere - | sec_or_group_p1 | ; statement_anywhere: ENTRY '(' NAME ')' - { lang_add_entry($3); } + { lang_add_entry ($3, 0); } | assignment end ; file_NAME_list: NAME { lang_add_wild($1, current_file); } - | file_NAME_list opt_comma NAME + | file_NAME_list opt_comma NAME { lang_add_wild($3, current_file); } ; @@ -418,70 +334,82 @@ input_section_spec: { lang_add_wild((char *)NULL, $1); } - | '[' + | '[' { current_file = (char *)NULL; } - file_NAME_list - ']' + file_NAME_list + ']' | NAME { - current_file =$1; - } + current_file =$1; + } '(' file_NAME_list ')' - | '*' - { + | '*' + { current_file = (char *)NULL; - } + } '(' file_NAME_list ')' ; statement: - statement assignment end - | statement ';' - | statement - | statement CREATE_OBJECT_SYMBOLS + assignment end + | CREATE_OBJECT_SYMBOLS { - lang_add_attribute(lang_object_symbols_statement_enum); } - | statement CONSTRUCTORS + lang_add_attribute(lang_object_symbols_statement_enum); + } + | ';' + | CONSTRUCTORS { - lang_add_attribute(lang_constructors_statement_enum); } - - | statement input_section_spec - | statement length '(' exp ')' + + lang_add_attribute(lang_constructors_statement_enum); + } + | input_section_spec + | length '(' exp ')' { - lang_add_data($2,$4); + lang_add_data((int) $1,$3); } - | statement FILL '(' exp ')' + | FILL '(' exp ')' { lang_add_fill - (exp_get_value_int($4, + (exp_get_value_int($3, 0, "fill value", lang_first_phase_enum)); } - | + ; + +statement_list: + statement_list statement + | statement + ; + +statement_list_opt: + /* empty */ + | statement_list ; length: - LONG + QUAD + { $$ = $1; } + | LONG { $$ = $1; } - | SHORT + | SHORT { $$ = $1; } - | BYTE + | BYTE { $$ = $1; } ; fill_opt: - '=' exp + '=' mustbe_exp { $$ = exp_get_value_int($2, 0, "fill value", - lang_first_phase_enum); + lang_first_phase_enum); } - | { $$ = 0; } + | { $$ = 0; } ; @@ -489,7 +417,7 @@ fill_opt: assign_op: PLUSEQ { $$ = '+'; } - | MINUSEQ + | MINUSEQ { $$ = '-'; } | MULTEQ { $$ = '*'; } @@ -506,20 +434,27 @@ assign_op: ; -end: ';' | ',' +end: ';' | ',' ; assignment: - NAME '=' exp + NAME '=' mustbe_exp { - lang_add_assignment(exp_assop($2,$1,$3)); + lang_add_assignment (exp_assop ($2, $1, $3)); } - | NAME assign_op exp + | NAME assign_op mustbe_exp { - lang_add_assignment(exp_assop('=',$1,exp_binop($2,exp_nameop(NAME,$1),$3))); + lang_add_assignment (exp_assop ('=', $1, + exp_binop ($2, + exp_nameop (NAME, + $1), + $3))); + } + | PROVIDE '(' NAME '=' mustbe_exp ')' + { + lang_add_assignment (exp_provide ($3, $5)); } - ; @@ -528,35 +463,30 @@ opt_comma: memory: - MEMORY '{' memory_spec memory_spec_list '}' + MEMORY '{' memory_spec memory_spec_list '}' ; memory_spec_list: - memory_spec_list memory_spec + memory_spec_list memory_spec | memory_spec_list ',' memory_spec | ; -memory_spec: - NAME +memory_spec: NAME { region = lang_memory_region_lookup($1); } - attributes_opt ':' origin_spec opt_comma length_spec - - { - + attributes_opt ':' + origin_spec opt_comma length_spec - } - ; -origin_spec: - ORIGIN '=' exp + ; origin_spec: + ORIGIN '=' mustbe_exp { region->current = region->origin = - exp_get_vma($3, 0L,"origin", lang_first_phase_enum); } - ; -length_spec: - LENGTH '=' exp - { region->length = exp_get_vma($3, + exp_get_vma($3, 0L,"origin", lang_first_phase_enum); +} + ; length_spec: + LENGTH '=' mustbe_exp + { region->length = exp_get_vma($3, ~((bfd_vma)0), "length", lang_first_phase_enum); @@ -578,13 +508,13 @@ startup: ; high_level_library: - HLL '(' high_level_library_NAME_list ')' - | HLL '(' ')' + HLL '(' high_level_library_NAME_list ')' + | HLL '(' ')' { ldemul_hll((char *)NULL); } ; high_level_library_NAME_list: - high_level_library_NAME_list opt_comma filename + high_level_library_NAME_list opt_comma filename { ldemul_hll($3); } | filename { ldemul_hll($1); } @@ -593,10 +523,9 @@ high_level_library_NAME_list: low_level_library: SYSLIB '(' low_level_library_NAME_list ')' - ; -low_level_library_NAME_list: + ; low_level_library_NAME_list: low_level_library_NAME_list opt_comma filename - { ldemul_syslib($3); } + { ldemul_syslib($3); } | ; @@ -604,24 +533,27 @@ floating_point_support: FLOAT { lang_float(true); } | NOFLOAT - { lang_float(false); } + { lang_float(false); } ; - +mustbe_exp: { ldlex_expression(); } + exp + { ldlex_popstate(); $$=$2;} + ; exp : - '-' exp %prec UNARY + '-' exp %prec UNARY { $$ = exp_unop('-', $2); } - | '(' exp ')' + | '(' exp ')' { $$ = $2; } | NEXT '(' exp ')' %prec UNARY - { $$ = exp_unop($1,$3); } - | '!' exp %prec UNARY + { $$ = exp_unop((int) $1,$3); } + | '!' exp %prec UNARY { $$ = exp_unop('!', $2); } - | '+' exp %prec UNARY + | '+' exp %prec UNARY { $$ = $2; } - | '~' exp %prec UNARY + | '~' exp %prec UNARY { $$ = exp_unop('~', $2);} | exp '*' exp @@ -633,7 +565,7 @@ exp : | exp '+' exp { $$ = exp_binop('+', $1, $3); } | exp '-' exp - { $$ = exp_binop('-' , $1, $3); } + { $$ = exp_binop('-' , $1, $3); } | exp LSHIFT exp { $$ = exp_binop(LSHIFT , $1, $3); } | exp RSHIFT exp @@ -644,7 +576,7 @@ exp : { $$ = exp_binop(NE , $1, $3); } | exp LE exp { $$ = exp_binop(LE , $1, $3); } - | exp GE exp + | exp GE exp { $$ = exp_binop(GE , $1, $3); } | exp '<' exp { $$ = exp_binop('<' , $1, $3); } @@ -666,64 +598,78 @@ exp : { $$ = exp_nameop(DEFINED, $3); } | INT { $$ = exp_intop($1); } - | SIZEOF_HEADERS + | SIZEOF_HEADERS { $$ = exp_nameop(SIZEOF_HEADERS,0); } - | SIZEOF '(' NAME ')' + | SIZEOF '(' NAME ')' { $$ = exp_nameop(SIZEOF,$3); } | ADDR '(' NAME ')' { $$ = exp_nameop(ADDR,$3); } + | ABSOLUTE '(' exp ')' + { $$ = exp_unop(ABSOLUTE, $3); } | ALIGN_K '(' exp ')' { $$ = exp_unop(ALIGN_K,$3); } + | BLOCK '(' exp ')' + { $$ = exp_unop(ALIGN_K,$3); } | NAME { $$ = exp_nameop(NAME,$1); } ; +opt_at: + AT '(' exp ')' { $$ = $3; } + | { $$ = 0; } + ; - -section: NAME opt_exp opt_type opt_block ':' opt_things'{' - { - lang_enter_output_section_statement($1,$2,$3,$4); - } - statement '}' fill_opt memspec_opt +section: NAME { ldlex_expression(); } + opt_exp_with_type + opt_at { ldlex_popstate(); } + '{' + { + lang_enter_output_section_statement($1,$3,typebits,0,0,0,$4); + } + statement_list_opt + '}' {ldlex_expression();} memspec_opt fill_opt { - lang_leave_output_section_statement($11, $12); + ldlex_popstate(); + lang_leave_output_section_statement($12, $11); } +opt_comma ; -opt_type: - '(' NOLOAD ')' { $$ = SEC_NO_FLAGS; } - | '(' DSECT ')' { $$ = 0; } - | '(' COPY ')' { $$ = 0; } - | '(' INFO ')' { $$ = 0; } - | '(' OVERLAY ')' { $$ = 0; } - | { $$ = SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS; } +type: + NOLOAD { typebits = SEC_NEVER_LOAD; } + | DSECT { typebits = 0; } + | COPY { typebits = 0; } + | INFO { typebits = 0; } + | OVERLAY { typebits = 0; } + | { typebits = SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS; } ; -opt_things: ; - -opt_exp: - exp - { $$ = $1; } - | { $$= (etree_type *)NULL; } +opt_exp_with_type: + exp ':' { $$ = $1; typebits =0;} + | exp '(' type ')' ':' { $$ = $1; } + | ':' { $$= (etree_type *)NULL; typebits = 0; } + | '(' type ')' ':' { $$= (etree_type *)NULL; } ; -opt_block: - BLOCK '(' exp ')' - { $$ = exp_get_value_int($3, - 1L, - "block", - lang_first_phase_enum); - } - | { $$ = 1; } - ; - memspec_opt: - '>' NAME + '>' NAME { $$ = $2; } | { $$ = "*default*"; } ; - +%% +void +yyerror(arg) + const char *arg; +{ + if (ldfile_assumed_script) + einfo ("%P:%s: file format not recognized; treating as linker script\n", + ldfile_input_filename); + if (error_index > 0 && error_index < ERROR_NAME_MAX) + einfo ("%P%F:%S: %s in %s\n", arg, error_names[error_index-1]); + else + einfo ("%P%F:%S: %s\n", arg); +}