summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTrygve Laugstøl <trygvis@inamo.no>2016-07-04 21:53:55 +0200
committerTrygve Laugstøl <trygvis@inamo.no>2016-07-04 21:53:55 +0200
commitc7fb7dfd794700bf6977a907a8612e9b644e4fe4 (patch)
tree57bd9a7f0499c795cf7aa9ba2f1c08ef406df847
parentead2f1961fc653861a151a033c3cd0657c50af16 (diff)
downloadintel-quark-d2000-playground-c7fb7dfd794700bf6977a907a8612e9b644e4fe4.tar.gz
intel-quark-d2000-playground-c7fb7dfd794700bf6977a907a8612e9b644e4fe4.tar.bz2
intel-quark-d2000-playground-c7fb7dfd794700bf6977a907a8612e9b644e4fe4.tar.xz
intel-quark-d2000-playground-c7fb7dfd794700bf6977a907a8612e9b644e4fe4.zip
o Improved parser.
-rw-r--r--cmake/elfinfo/.gitignore1
-rw-r--r--cmake/elfinfo/GnuLdLexer.g4209
-rw-r--r--cmake/elfinfo/GnuLdParser.g4 (renamed from cmake/elfinfo/GnuLd.g4)521
-rwxr-xr-xcmake/elfinfo/g4.sh11
-rw-r--r--cmake/elfinfo/pom.xml57
-rw-r--r--cmake/elfinfo/src/main/antlr4/Test1Lexer.g422
-rw-r--r--cmake/elfinfo/src/main/antlr4/Test1Parser.g423
-rw-r--r--cmake/elfinfo/src/main/java/io/trygvis/ld/CollectingErrorListener.java17
-rw-r--r--cmake/elfinfo/src/main/java/io/trygvis/ld/LdScript.java73
-rw-r--r--cmake/elfinfo/src/main/java/io/trygvis/ld/StringGnuLdVisitor.java59
-rw-r--r--cmake/elfinfo/src/main/test/io/trygvis/ld/FullScriptsTest.java34
-rw-r--r--cmake/elfinfo/src/main/test/io/trygvis/ld/InputSectionSpecTest.java38
-rw-r--r--cmake/elfinfo/src/main/test/io/trygvis/ld/NameTest.java50
-rw-r--r--cmake/elfinfo/src/main/test/io/trygvis/ld/SystemOutReportingErrorListener.java32
-rw-r--r--cmake/elfinfo/src/main/test/io/trygvis/ld/test1/Test1Test.java102
15 files changed, 880 insertions, 369 deletions
diff --git a/cmake/elfinfo/.gitignore b/cmake/elfinfo/.gitignore
index a2d5086..db5702a 100644
--- a/cmake/elfinfo/.gitignore
+++ b/cmake/elfinfo/.gitignore
@@ -3,3 +3,4 @@
*.iws
*.jar
/antlr
+*.tokens
diff --git a/cmake/elfinfo/GnuLdLexer.g4 b/cmake/elfinfo/GnuLdLexer.g4
new file mode 100644
index 0000000..fba488e
--- /dev/null
+++ b/cmake/elfinfo/GnuLdLexer.g4
@@ -0,0 +1,209 @@
+lexer grammar GnuLdLexer;
+
+
+//%token <token>
+LBRACE : '{';
+RBRACE : '}';
+
+// <integer>
+// <token> assign_op atype attributes_opt sect_constraint opt_align_with_input
+// <name> filename
+//%type <versyms> vers_defns
+//%type <versnode> vers_tag
+//%type <deflist> verdep
+
+ABSOLUTE : 'ABSOLUTE';
+ADDR : 'ADDR';
+AFTER : 'AFTER';
+ALIAS : 'ALIAS';
+//ALIGN : 'ALIGN';
+ALIGN_K : 'ALIGN';
+ALIGNMOD : 'ALIGNMOD';
+ALIGNOF : 'ALIGNOF';
+ALIGN_WITH_INPUT : 'ALIGN_WITH_INPUT';
+AS_NEEDED : 'AS_NEEDED';
+ASSERT_K : 'ASSERT';
+AT : 'AT';
+BASE : 'BASE';
+BEFORE : 'BEFORE';
+BIND : 'BIND';
+BLOCK : 'BLOCK';
+BYTE : 'BYTE';
+CASE : 'CASE';
+CHIP : 'CHIP';
+CONSTANT : 'CONSTANT';
+CONSTRUCTORS : 'CONSTRUCTORS';
+COPY : 'COPY';
+CREATE_OBJECT_SYMBOLS : 'CREATE_OBJECT_SYMBOLS';
+DATA_SEGMENT_ALIGN : 'DATA_SEGMENT_ALIGN';
+DATA_SEGMENT : 'DATA_SEGMENT';
+DATA_SEGMENT_END : 'DATA_SEGMENT_END';
+DATA_SEGMENT_RELRO_END : 'DATA_SEGMENT_RELRO_END';
+DEFINED : 'DEFINED';
+DEFSYMEND : 'DEFSYMEND';
+DSECT : 'DSECT';
+ENDWORD : 'ENDWORD';
+ENTRY : 'ENTRY';
+EXCLUDE_FILE : 'EXCLUDE_FILE';
+EXTERN : 'EXTERN';
+FILL : 'FILL';
+FLOAT : 'FLOAT';
+FORCE_COMMON_ALLOCATION : 'FORCE_COMMON_ALLOCATION';
+FORMAT : 'FORMAT';
+GLOBAL : 'GLOBAL';
+GROUP : 'GROUP';
+HIDDEN_ : 'HIDDEN';
+HLL : 'HLL';
+INCLUDE : 'INCLUDE';
+INFO : 'INFO';
+INHIBIT_COMMON_ALLOCATION : 'INHIBIT_COMMON_ALLOCATION';
+//INPUT_DEFSYM : 'INPUT_DEFSYM';
+//INPUT_DYNAMIC_LIST : 'INPUT_DYNAMIC_LIST';
+INPUT : 'INPUT';
+//INPUT_MRI_SCRIPT : 'INPUT_MRI_SCRIPT';
+//INPUT_SCRIPT : 'INPUT_SCRIPT';
+//INPUT_SECTION_FLAGS : 'INPUT_SECTION_FLAGS';
+//INPUT_VERSION_SCRIPT : 'INPUT_VERSION_SCRIPT';
+INSERT_K : 'INSERT';
+KEEP : 'KEEP';
+LD_FEATURE : 'LD_FEATURE';
+LENGTH : 'LENGTH';
+LIST : 'LIST';
+LOADADDR : 'LOADADDR';
+LOAD : 'LOAD';
+LOCAL : 'LOCAL';
+LOG2CEIL : 'LOG2CEIL';
+LONG : 'LONG';
+MAP : 'MAP';
+MAX_K : 'MAX';
+MEMORY : 'MEMORY';
+MIN_K : 'MIN';
+NAMEWORD : 'NAMEWORD';
+NEWLINE : 'NEWLINE';
+NEXT : 'NEXT';
+NOCROSSREFS : 'NOCROSSREFS';
+NOCROSSREFS_TO : 'NOCROSSREFS_TO';
+NOFLOAT : 'NOFLOAT';
+NOLOAD : 'NOLOAD';
+ONLY_IF_RO : 'ONLY_IF_RO';
+ONLY_IF_RW : 'ONLY_IF_RW';
+ORDER : 'ORDER';
+ORIGIN : 'ORIGIN'; // TODO: or 'org' or 'o'.
+OUTPUT_ARCH : 'OUTPUT_ARCH';
+OUTPUT_FORMAT : 'OUTPUT_FORMAT';
+OUTPUT : 'OUTPUT';
+OVERLAY : 'OVERLAY';
+PHDRS : 'PHDRS';
+PROVIDE_HIDDEN : 'PROVIDE_HIDDEN';
+PROVIDE : 'PROVIDE';
+PUBLIC : 'PUBLIC';
+QUAD : 'QUAD';
+REGION_ALIAS : 'REGION_ALIAS';
+REL : 'REL';
+SEARCH_DIR : 'SEARCH_DIR';
+SECTIONS : 'SECTIONS';
+SECT : 'SECT';
+SEGMENT_START : 'SEGMENT_START';
+SHORT : 'SHORT';
+SIZEOF_HEADERS : 'SIZEOF_HEADERS';
+SIZEOF : 'SIZEOF';
+SORT_BY_ALIGNMENT : 'SORT_BY_ALIGNMENT';
+SORT_BY_INIT_PRIORITY : 'SORT_BY_INIT_PRIORITY';
+SORT_BY_NAME : 'SORT_BY_NAME';
+SORT_NONE : 'SORT_NONE';
+SPECIAL : 'SPECIAL';
+SQUAD : 'SQUAD';
+START : 'START';
+STARTUP : 'STARTUP';
+SUBALIGN : 'SUBALIGN';
+SYSLIB : 'SYSLIB';
+TARGET_K : 'TARGET';
+TRUNCATE : 'TRUNCATE';
+VERS_IDENTIFIER : 'VERS_IDENTIFIER';
+VERSIONK : 'VERSIONK';
+VERS_TAG : 'VERS_TAG';
+
+/*
+Names are very liberal, they can be full strings and start with a dot.
+*/
+
+QUOTE : '"' -> skip, pushMode(STRING);
+
+//SPACE : ' ';
+//SPACES : ' '+;
+
+//name :
+// '"' (NAME | SPACE | SPACES)+ '"' # nameQuoted
+// | NAME # namePlain;
+
+//NAME : [\._a-zA-Z][\._a-zA-Z0-9]*;
+NAME : [*\._a-zA-Z][*\.\/_a-zA-Z0-9]*;
+
+// TODO: ld supports some really fancy expressions here, like "0101010b", "ffH", "ffx", "$Aa" etc
+//INT : '0x' [0-9a-fA-F]+
+// | [0-9]+;
+INT : INT_NUMBER INT_SIZE?;
+fragment
+INT_NUMBER : INT_HEX
+ | INT_DECIMAL;
+fragment
+INT_HEX : '0x' [0-9a-fA-F]+;
+fragment
+INT_DECIMAL : [0-9]+;
+fragment
+INT_SIZE : 'M' | 'm' | 'K' | 'k';
+
+END : 'END';
+
+LNAME : '-l' NAME;
+PLUSEQ : '+=';
+MINUSEQ : '-=';
+MULTEQ : '*=';
+DIVEQ : '/=';
+LSHIFTEQ : '<<=';
+RSHIFTEQ : '>>=';
+ANDEQ : '&=';
+OREQ : '|=';
+LSHIFT : '<<';
+RSHIFT : '>>';
+EQEQ : '==';
+EQ : '=';
+NE : '!=';
+LE : '<=';
+GE : '>=';
+ANDAND : '&&';
+OROR : '||';
+
+// Extra tokens
+COLON : ':';
+EXLAMATION : '!';
+DASH : '-';
+PLUS : '+';
+TILDE : '~';
+SLASH : '/';
+MOD : '%';
+LT : '<';
+GT : '>';
+HAT : '^';
+BAR : '|';
+COMMA : ',';
+SEMICOLON : ';';
+LPAREN : '(';
+RPAREN : ')';
+STAR : '*';
+QUESTION : '?';
+AMPERSAND : '&';
+LBRACKET : '[';
+RBRACKET : ']';
+
+BlockComment
+ : '/*' .*? '*/' -> skip
+ ;
+
+WS
+ : [ \t\r\n]+ -> skip
+ ;
+
+mode STRING;
+STRING_ANY : ~'"';
+STRING_END_QUOTE : '"' -> skip, popMode;
diff --git a/cmake/elfinfo/GnuLd.g4 b/cmake/elfinfo/GnuLdParser.g4
index da7b01f..1ed1119 100644
--- a/cmake/elfinfo/GnuLd.g4
+++ b/cmake/elfinfo/GnuLdParser.g4
@@ -1,4 +1,8 @@
-grammar GnuLd;
+parser grammar GnuLdParser;
+
+options {
+ tokenVocab = GnuLdLexer;
+}
/*
TODO: check right associative annotations
@@ -12,7 +16,7 @@ TODO: check right associative annotations
/*
%right UNARY
%token END
-%left <token> '('
+%left <token> LPAREN
*/
@@ -29,7 +33,7 @@ filename: NAME;
defsym_expr:
// { ldlex_defsym(); }
- NAME '=' exp
+ NAME EQ exp
// {
// ldlex_popstate();
// lang_add_assignment (exp_defsym ($2, $4));
@@ -57,7 +61,7 @@ mri_script_lines:
mri_script_command:
CHIP exp
- | CHIP exp ',' exp
+ | CHIP exp COMMA exp
| NAME /*{
einfo(_("%P%F: unrecognised keyword in MRI style script '%s'\n"),$1);
}*/
@@ -66,35 +70,35 @@ mri_script_command:
}*/
| ORDER ordernamelist
| ENDWORD
- | PUBLIC NAME '=' exp
+ | PUBLIC NAME EQ exp
// { mri_public($2, $4); }
- | PUBLIC NAME ',' exp
+ | PUBLIC NAME COMMA exp
// { mri_public($2, $4); }
| PUBLIC NAME exp
// { mri_public($2, $3); }
| FORMAT NAME
// { mri_format($2); }
- | SECT NAME ',' exp
+ | SECT NAME COMMA exp
// { mri_output_section($2, $4);}
| SECT NAME exp
// { mri_output_section($2, $3);}
- | SECT NAME '=' exp
+ | SECT NAME EQ exp
// { mri_output_section($2, $4);}
- | ALIGN_K NAME '=' exp
+ | ALIGN_K NAME EQ exp
// { mri_align($2,$4); }
- | ALIGN_K NAME ',' exp
+ | ALIGN_K NAME COMMA exp
// { mri_align($2,$4); }
- | ALIGNMOD NAME '=' exp
+ | ALIGNMOD NAME EQ exp
// { mri_alignmod($2,$4); }
- | ALIGNMOD NAME ',' exp
+ | 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 ',' NAME
+ | ALIAS NAME COMMA NAME
// { mri_alias($2,$4,0);}
- | ALIAS NAME ',' INT
+ | ALIAS NAME COMMA INT
// { mri_alias ($2, 0, (int) $4.integer); }
| BASE exp
// { mri_base($2); }
@@ -112,7 +116,7 @@ mri_script_command:
;
ordernamelist:
- ordernamelist ',' NAME // { mri_order($3); }
+ ordernamelist COMMA NAME // { mri_order($3); }
| ordernamelist NAME // { mri_order($2); }
|
;
@@ -120,20 +124,20 @@ ordernamelist:
mri_load_name_list:
NAME
// { mri_load($1); }
- | mri_load_name_list ',' NAME // { mri_load($3); }
+ | mri_load_name_list COMMA NAME // { mri_load($3); }
;
mri_abs_name_list:
NAME
// { mri_only_load($1); }
- | mri_abs_name_list ',' NAME
+ | mri_abs_name_list COMMA NAME
// { mri_only_load($3); }
;
casesymlist:
/* empty */ // { $$ = NULL; }
| NAME
- | casesymlist ',' NAME
+ | casesymlist COMMA NAME
;
/* Parsed as expressions so that commas separate entries */
@@ -148,7 +152,7 @@ extern_name_list_body:
// { ldlang_add_undef ($1, FALSE); }
| extern_name_list_body NAME
// { ldlang_add_undef ($2, FALSE); }
- | extern_name_list_body ',' NAME
+ | extern_name_list_body COMMA NAME
// { ldlang_add_undef ($3, FALSE); }
;
@@ -174,51 +178,51 @@ ifile_p1:
| floating_point_support
| statement_anywhere
| version
- | ';'
- | TARGET_K '(' NAME ')'
+ | SEMICOLON
+ | TARGET_K LPAREN NAME RPAREN
// { lang_add_target($3); }
- | SEARCH_DIR '(' filename ')'
+ | SEARCH_DIR LPAREN filename RPAREN
// { ldfile_add_library_path ($3, FALSE); }
- | OUTPUT '(' filename ')'
+ | OUTPUT LPAREN filename RPAREN
// { lang_add_output($3, 1); }
- | OUTPUT_FORMAT '(' NAME ')'
+ | OUTPUT_FORMAT LPAREN NAME RPAREN
// { lang_add_output_format ($3, (char *) NULL,
// (char *) NULL, 1); }
- | OUTPUT_FORMAT '(' NAME ',' NAME ',' NAME ')'
+ | OUTPUT_FORMAT LPAREN NAME COMMA NAME COMMA NAME RPAREN
// { lang_add_output_format ($3, $5, $7, 1); }
- | OUTPUT_ARCH '(' NAME ')'
+ | 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 '(' input_list ')'
+ | INPUT LPAREN input_list RPAREN
| GROUP
// { lang_enter_group (); }
- '(' input_list ')'
+ LPAREN input_list RPAREN
// { lang_leave_group (); }
- | MAP '(' filename ')'
+ | MAP LPAREN filename RPAREN
// { lang_add_map($3); }
| INCLUDE filename
// { ldlex_script (); ldfile_open_command_file($2); }
ifile_list END
// { ldlex_popstate (); }
- | NOCROSSREFS '(' nocrossref_list ')'
+ | NOCROSSREFS LPAREN nocrossref_list RPAREN
// {
// lang_add_nocrossref ($3);
// }
- | NOCROSSREFS_TO '(' nocrossref_list ')'
+ | NOCROSSREFS_TO LPAREN nocrossref_list RPAREN
// {
// lang_add_nocrossref_to ($3);
// }
- | EXTERN '(' extern_name_list ')'
+ | 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 '(' NAME ',' NAME ')'
+ | REGION_ALIAS LPAREN NAME COMMA NAME RPAREN
// { lang_memory_region_alias ($3, $5); }
- | LD_FEATURE '(' NAME ')'
+ | LD_FEATURE LPAREN NAME RPAREN
// { lang_ld_feature ($3); }
;
@@ -232,7 +236,7 @@ input_list1:
NAME
// { lang_add_input_file($1,lang_input_file_is_search_file_enum,
// (char *)NULL); }
- | input_list1 ',' NAME
+ | input_list1 COMMA NAME
// { lang_add_input_file($3,lang_input_file_is_search_file_enum,
// (char *)NULL); }
| input_list1 NAME
@@ -241,31 +245,31 @@ input_list1:
| LNAME
// { lang_add_input_file($1,lang_input_file_is_l_enum,
// (char *)NULL); }
- | input_list1 ',' LNAME
+ | 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 '('
+ | AS_NEEDED LPAREN
// { $<integer>$ = input_flags.add_DT_NEEDED_for_regular;
// input_flags.add_DT_NEEDED_for_regular = TRUE; }
- // input_list1 ')'
+ // input_list1 RPAREN
// { input_flags.add_DT_NEEDED_for_regular = $<integer>3; }
- | input_list1 ',' AS_NEEDED '('
+ | input_list1 COMMA AS_NEEDED LPAREN
// { $<integer>$ = input_flags.add_DT_NEEDED_for_regular;
// input_flags.add_DT_NEEDED_for_regular = TRUE; }
- // input_list1 ')'
+ // input_list1 RPAREN
// { input_flags.add_DT_NEEDED_for_regular = $<integer>5; }
- | input_list1 AS_NEEDED '('
+ | input_list1 AS_NEEDED LPAREN
// { $<integer>$ = input_flags.add_DT_NEEDED_for_regular;
// input_flags.add_DT_NEEDED_for_regular = TRUE; }
- // input_list1 ')'
+ // input_list1 RPAREN
// { input_flags.add_DT_NEEDED_for_regular = $<integer>4; }
;
sections:
- SECTIONS '{' sec_or_group_p1 '}'
+ SECTIONS LBRACE sec_or_group_p1 RBRACE
;
sec_or_group_p1:
@@ -275,26 +279,26 @@ sec_or_group_p1:
;
statement_anywhere:
- ENTRY '(' NAME ')'
+ ENTRY LPAREN NAME RPAREN
// { lang_add_entry ($3, FALSE); }
| assignment end
- | ASSERT_K /*{ldlex_expression ();}*/ '(' exp ',' NAME ')'
+ | 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. */
+ separate tokens rather than as name. */
wildcard_name:
NAME
// {
// $$ = $1;
// }
- | '*'
+ | STAR
// {
// $$ = "*";
// }
- | '?'
+ | QUESTION
// {
// $$ = "?";
// }
@@ -308,70 +312,70 @@ wildcard_spec:
// $$.exclude_name_list = NULL;
// $$.section_flag_list = NULL;
// }
- | EXCLUDE_FILE '(' exclude_name_list ')' wildcard_name
+ | EXCLUDE_FILE LPAREN exclude_name_list RPAREN wildcard_name
// {
// $$.name = $5;
// $$.sorted = none;
// $$.exclude_name_list = $3;
// $$.section_flag_list = NULL;
// }
- | SORT_BY_NAME '(' wildcard_name ')'
+ | SORT_BY_NAME LPAREN wildcard_name RPAREN
// {
// $$.name = $3;
// $$.sorted = by_name;
// $$.exclude_name_list = NULL;
// $$.section_flag_list = NULL;
// }
- | SORT_BY_ALIGNMENT '(' wildcard_name ')'
+ | SORT_BY_ALIGNMENT LPAREN wildcard_name RPAREN
// {
// $$.name = $3;
// $$.sorted = by_alignment;
// $$.exclude_name_list = NULL;
// $$.section_flag_list = NULL;
// }
- | SORT_NONE '(' wildcard_name ')'
+ | SORT_NONE LPAREN wildcard_name RPAREN
// {
// $$.name = $3;
// $$.sorted = by_none;
// $$.exclude_name_list = NULL;
// $$.section_flag_list = NULL;
// }
- | SORT_BY_NAME '(' SORT_BY_ALIGNMENT '(' wildcard_name ')' ')'
+ | 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 '(' SORT_BY_NAME '(' wildcard_name ')' ')'
+ | 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 '(' SORT_BY_NAME '(' wildcard_name ')' ')'
+ | 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 '(' SORT_BY_ALIGNMENT '(' wildcard_name ')' ')'
+ | 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 '(' EXCLUDE_FILE '(' exclude_name_list ')' wildcard_name ')'
+ | 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 '(' wildcard_name ')'
+ | SORT_BY_INIT_PRIORITY LPAREN wildcard_name RPAREN
// {
// $$.name = $3;
// $$.sorted = by_init_priority;
@@ -398,7 +402,7 @@ sect_flag_list: NAME
// n->next = NULL;
// $$ = n;
// }
- | sect_flag_list '&' NAME
+ | sect_flag_list AMPERSAND NAME
// {
// struct flag_info_list *n;
// n = ((struct flag_info_list *) xmalloc (sizeof *n));
@@ -419,7 +423,7 @@ sect_flag_list: NAME
;
sect_flags:
- /*not used by antlr: INPUT_SECTION_FLAGS*/ '(' sect_flag_list ')'
+ /*not used by antlr: INPUT_SECTION_FLAGS*/ LPAREN sect_flag_list RPAREN
// {
// struct flag_info *n;
// n = ((struct flag_info *) xmalloc (sizeof *n));
@@ -451,8 +455,8 @@ exclude_name_list:
// }
;
-file_NAME_list:
- file_NAME_list opt_comma wildcard_spec
+file_name_list:
+ file_name_list opt_comma wildcard_spec
// {
// struct wildcard_list *tmp;
// tmp = (struct wildcard_list *) xmalloc (sizeof *tmp);
@@ -490,11 +494,11 @@ input_section_spec_no_keep:
// tmp.section_flag_list = $1;
// lang_add_wild (&tmp, NULL, ldgram_had_keep);
// }
- | '[' file_NAME_list ']'
+ | LBRACKET file_name_list RBRACKET
// {
// lang_add_wild (NULL, $2, ldgram_had_keep);
// }
- | sect_flags '[' file_NAME_list ']'
+ | sect_flags LBRACKET file_name_list RBRACKET
// {
// struct wildcard_spec tmp;
// tmp.name = NULL;
@@ -503,11 +507,11 @@ input_section_spec_no_keep:
// tmp.section_flag_list = $1;
// lang_add_wild (&tmp, $3, ldgram_had_keep);
// }
- | wildcard_spec '(' file_NAME_list ')'
+ | wildcard_spec LPAREN file_name_list RPAREN
// {
// lang_add_wild (&$1, $3, ldgram_had_keep);
// }
- | sect_flags wildcard_spec '(' file_NAME_list ')'
+ | sect_flags wildcard_spec LPAREN file_name_list RPAREN
// {
// $2.section_flag_list = $1;
// lang_add_wild (&$2, $4, ldgram_had_keep);
@@ -516,9 +520,9 @@ input_section_spec_no_keep:
input_section_spec:
input_section_spec_no_keep
- | KEEP '('
+ | KEEP LPAREN
// { ldgram_had_keep = TRUE; }
- input_section_spec_no_keep ')'
+ input_section_spec_no_keep RPAREN
// { ldgram_had_keep = FALSE; }
;
@@ -528,28 +532,28 @@ statement:
// {
// lang_add_attribute(lang_object_symbols_statement_enum);
// }
- | ';'
+ | SEMICOLON
| CONSTRUCTORS
// {
//
// lang_add_attribute(lang_constructors_statement_enum);
// }
- | SORT_BY_NAME '(' CONSTRUCTORS ')'
+ | SORT_BY_NAME LPAREN CONSTRUCTORS RPAREN
// {
// constructors_sorted = TRUE;
// lang_add_attribute (lang_constructors_statement_enum);
// }
| input_section_spec
- | length '(' mustbe_exp ')'
+ | length LPAREN mustbe_exp RPAREN
// {
// lang_add_data ((int) $1, $3);
// }
- | FILL '(' fill_exp ')'
+ | FILL LPAREN fill_exp RPAREN
// {
// lang_add_fill ($3);
// }
- | ASSERT_K /*{ldlex_expression ();}*/ '(' exp ',' NAME ')' end
+ | ASSERT_K /*{ldlex_expression ();}*/ LPAREN exp COMMA NAME RPAREN end
// { ldlex_popstate ();
// lang_add_assignment (exp_assert ($4, $6)); }
| INCLUDE filename
@@ -589,7 +593,7 @@ fill_exp:
;
fill_opt:
- '=' fill_exp
+ EQ fill_exp
// { $$ = $2; }
| // { $$ = (fill_type *) 0; }
;
@@ -614,12 +618,12 @@ assign_op:
;
-end: ';' | ','
+end: SEMICOLON | COMMA
;
assignment:
- NAME '=' mustbe_exp
+ NAME EQ mustbe_exp
// {
// lang_add_assignment (exp_assign ($1, $3, FALSE));
// }
@@ -631,15 +635,15 @@ assignment:
// $1),
// $3), FALSE));
// }
- | HIDDEN_ '(' NAME '=' mustbe_exp ')'
+ | HIDDEN_ LPAREN NAME EQ mustbe_exp RPAREN
// {
// lang_add_assignment (exp_assign ($3, $5, TRUE));
// }
- | PROVIDE '(' NAME '=' mustbe_exp ')'
+ | PROVIDE LPAREN NAME EQ mustbe_exp RPAREN
// {
// lang_add_assignment (exp_provide ($3, $5, FALSE));
// }
- | PROVIDE_HIDDEN '(' NAME '=' mustbe_exp ')'
+ | PROVIDE_HIDDEN LPAREN NAME EQ mustbe_exp RPAREN
// {
// lang_add_assignment (exp_provide ($3, $5, TRUE));
// }
@@ -647,11 +651,11 @@ assignment:
opt_comma:
- ',' | ;
+ COMMA | ;
memory:
- MEMORY '{' memory_spec_list_opt '}'
+ MEMORY LBRACE memory_spec_list_opt RBRACE
;
memory_spec_list_opt: memory_spec_list | ;
@@ -664,7 +668,7 @@ memory_spec_list:
memory_spec: NAME
// { region = lang_memory_region_lookup ($1, TRUE); }
- attributes_opt ':'
+ attributes_opt COLON
origin_spec opt_comma length_spec
// {}
| INCLUDE filename
@@ -674,7 +678,7 @@ memory_spec: NAME
;
origin_spec:
- ORIGIN '=' mustbe_exp
+ ORIGIN EQ mustbe_exp
// {
// region->origin_exp = $3;
// region->current = region->origin;
@@ -682,7 +686,7 @@ origin_spec:
;
length_spec:
- LENGTH '=' mustbe_exp
+ LENGTH EQ mustbe_exp
// {
// region->length_exp = $3;
// }
@@ -691,7 +695,7 @@ length_spec:
attributes_opt:
/* empty */
/* { *//* dummy action to avoid bison 1.25 error message *//* }
- |*/ '(' attributes_list ')'
+ |*/ LPAREN attributes_list RPAREN
;
attributes_list:
@@ -702,7 +706,7 @@ attributes_list:
attributes_string:
NAME # attributeNormal
// { lang_set_flags (region, $1, 0); }
- | '!' NAME # attributeInverted
+ | EXLAMATION NAME # attributeInverted
// { lang_set_flags (region, $2, 1); }
;
@@ -718,13 +722,13 @@ attributes_string :
attribute: 'r' | 'w' | 'x' | 'a' | 'i' | 'l' ;
*/
startup:
- STARTUP '(' filename ')'
+ STARTUP LPAREN filename RPAREN
// { lang_startup($3); }
;
high_level_library:
- HLL '(' high_level_library_NAME_list ')'
- | HLL '(' ')'
+ HLL LPAREN high_level_library_NAME_list RPAREN
+ | HLL LPAREN RPAREN
// { ldemul_hll((char *)NULL); }
;
@@ -737,7 +741,7 @@ high_level_library_NAME_list:
;
low_level_library:
- SYSLIB '(' low_level_library_NAME_list ')'
+ SYSLIB LPAREN low_level_library_NAME_list RPAREN
; low_level_library_NAME_list:
low_level_library_NAME_list opt_comma filename
// { ldemul_syslib($3); }
@@ -765,7 +769,7 @@ nocrossref_list:
// n->next = $2;
// $$ = n;
// }
- | NAME ',' nocrossref_list
+ | NAME COMMA nocrossref_list
// {
// struct lang_nocrossref *n;
//
@@ -782,33 +786,33 @@ mustbe_exp: // { ldlex_expression (); }
;
exp :
- '-' exp # expNegate // TODO: %prec UNARY
+ DASH exp # expNegate // TODO: %prec UNARY
// { $$ = exp_unop ('-', $2); }
- | '(' exp ')' # expParen
+ | LPAREN exp RPAREN # expParen
// { $$ = $2; }
- | NEXT '(' exp ')' # expNextParen // TODO: %prec UNARY
+ | NEXT LPAREN exp RPAREN # expNextParen // TODO: %prec UNARY
// { $$ = exp_unop ((int) $1,$3); }
- | '!' exp # expInvert // TODO: %prec UNARY
+ | EXLAMATION exp # expInvert // TODO: %prec UNARY
// { $$ = exp_unop ('!', $2); }
- | '+' exp # expPlus // TODO: %prec UNARY
+ | PLUS exp # expPlus // TODO: %prec UNARY
// { $$ = $2; }
- | '~' exp # expMinus // TODO: %prec UNARY
+ | TILDE exp # expMinus // TODO: %prec UNARY
// { $$ = exp_unop ('~', $2);}
- | exp '*' exp # expMul
+ | exp STAR exp # expMul
// { $$ = exp_binop ('*', $1, $3); }
- | exp '/' exp # expDiv
+ | exp SLASH exp # expDiv
// { $$ = exp_binop ('/', $1, $3); }
- | exp '%' exp # expMod
+ | exp MOD exp # expMod
// { $$ = exp_binop ('%', $1, $3); }
- | exp '+' exp # expAdd
+ | exp PLUS exp # expAdd
// { $$ = exp_binop ('+', $1, $3); }
- | exp '-' exp # expSub
+ | 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 EQ exp # expEq
+ | exp EQEQ exp # expEq
// { $$ = exp_binop (EQ , $1, $3); }
| exp NE exp # expNe
// { $$ = exp_binop (NE , $1, $3); }
@@ -816,51 +820,51 @@ exp :
// { $$ = exp_binop (LE , $1, $3); }
| exp GE exp # expGe
// { $$ = exp_binop (GE , $1, $3); }
- | exp '<' exp # expGt
+ | exp LT exp # expLt
// { $$ = exp_binop ('<' , $1, $3); }
- | exp '>' exp # expLt
+ | exp GT exp # expGt
// { $$ = exp_binop ('>' , $1, $3); }
- | exp '&' exp # expAnd
+ | exp AMPERSAND exp # expAnd
// { $$ = exp_binop ('&' , $1, $3); }
- | exp '^' exp # expXor
+ | exp HAT exp # expXor
// { $$ = exp_binop ('^' , $1, $3); }
- | exp '|' exp # expOr
+ | exp BAR exp # expOr
// { $$ = exp_binop ('|' , $1, $3); }
- | exp '?' exp ':' exp # expTrinary
+ | 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 '(' NAME ')' # expDefined
+ | 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 '(' NAME ')' # expAlignof
+ | ALIGNOF LPAREN NAME RPAREN # expAlignof
// { $$ = exp_nameop (ALIGNOF,$3); }
- | SIZEOF '(' NAME ')' # expSizeof
+ | SIZEOF LPAREN NAME RPAREN # expSizeof
// { $$ = exp_nameop (SIZEOF,$3); }
- | ADDR '(' NAME ')' # expAddr
+ | ADDR LPAREN NAME RPAREN # expAddr
// { $$ = exp_nameop (ADDR,$3); }
- | LOADADDR '(' NAME ')' # expLoadaddr
+ | LOADADDR LPAREN NAME RPAREN # expLoadaddr
// { $$ = exp_nameop (LOADADDR,$3); }
- | CONSTANT '(' NAME ')' # expConstant
+ | CONSTANT LPAREN NAME RPAREN # expConstant
// { $$ = exp_nameop (CONSTANT,$3); }
- | ABSOLUTE '(' exp ')' # expAbsolute
+ | ABSOLUTE LPAREN exp RPAREN # expAbsolute
// { $$ = exp_unop (ABSOLUTE, $3); }
- | ALIGN_K '(' exp ')' # expAlign
+ | ALIGN_K LPAREN exp RPAREN # expAlign
// { $$ = exp_unop (ALIGN_K,$3); }
- | ALIGN_K '(' exp ',' exp ')' # expAlign2
+ | ALIGN_K LPAREN exp COMMA exp RPAREN # expAlignK
// { $$ = exp_binop (ALIGN_K,$3,$5); }
- | DATA_SEGMENT_ALIGN '(' exp ',' exp ')' # expDataSegmentAlign
+ | DATA_SEGMENT_ALIGN LPAREN exp COMMA exp RPAREN # expDataSegmentAlign
// { $$ = exp_binop (DATA_SEGMENT_ALIGN, $3, $5); }
- | DATA_SEGMENT_RELRO_END '(' exp ',' exp ')' # expDataSegmentRelRoEnd
+ | DATA_SEGMENT_RELRO_END LPAREN exp COMMA exp RPAREN # expDataSegmentRelRoEnd
// { $$ = exp_binop (DATA_SEGMENT_RELRO_END, $5, $3);
- | DATA_SEGMENT_END '(' exp ')' # expDataSegmentEnd
+ | DATA_SEGMENT_END LPAREN exp RPAREN # expDataSegmentEnd
// { $$ = exp_unop (DATA_SEGMENT_END, $3); }
- | SEGMENT_START '(' NAME ',' exp ')' # expSegmentStart
+ | 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
@@ -869,37 +873,37 @@ exp :
// $$ = exp_binop (SEGMENT_START,
// $5,
// exp_nameop (NAME, $3)); }
- | BLOCK '(' exp ')' # expBlock
+ | BLOCK LPAREN exp RPAREN # expBlock
// { $$ = exp_unop (ALIGN_K,$3); }
| NAME # expName
// { $$ = exp_nameop (NAME,$1); }
- | MAX_K '(' exp ',' exp ')' # expMax
+ | MAX_K LPAREN exp COMMA exp RPAREN # expMax
// { $$ = exp_binop (MAX_K, $3, $5 ); }
- | MIN_K '(' exp ',' exp ')' # expMin
+ | MIN_K LPAREN exp COMMA exp RPAREN # expMin
// { $$ = exp_binop (MIN_K, $3, $5 ); }
- | ASSERT_K '(' exp ',' NAME ')' # expAssert
+ | ASSERT_K LPAREN exp COMMA NAME RPAREN # expAssert
// { $$ = exp_assert ($3, $5); }
- | ORIGIN '(' NAME ')' # expOrigin
+ | ORIGIN LPAREN NAME RPAREN # expOrigin
// { $$ = exp_nameop (ORIGIN, $3); }
- | LENGTH '(' NAME ')' # expLengthExp
+ | LENGTH LPAREN NAME RPAREN # expLengthExp
// { $$ = exp_nameop (LENGTH, $3); }
- | LOG2CEIL '(' exp ')' # expLog2ceil
+ | LOG2CEIL LPAREN exp RPAREN # expLog2ceil
// { $$ = exp_unop (LOG2CEIL, $3); }
;
memspec_at_opt:
- AT '>' NAME // { $$ = $3; }
+ AT GT NAME // { $$ = $3; }
| // { $$ = 0; }
;
opt_at:
- AT '(' exp ')' // { $$ = $3; }
+ AT LPAREN exp RPAREN // { $$ = $3; }
| // { $$ = 0; }
;
opt_align:
- ALIGN_K '(' exp ')' // { $$ = $3; }
+ ALIGN_K LPAREN exp RPAREN // { $$ = $3; }
| // { $$ = 0; }
;
@@ -909,7 +913,7 @@ opt_align_with_input:
;
opt_subalign:
- SUBALIGN '(' exp ')' // { $$ = $3; }
+ SUBALIGN LPAREN exp RPAREN // { $$ = $3; }
| // { $$ = 0; }
;
@@ -927,14 +931,14 @@ section: NAME // { ldlex_expression(); }
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
- '}' // { ldlex_popstate (); ldlex_expression (); }
+ RBRACE // { ldlex_popstate (); ldlex_expression (); }
memspec_opt memspec_at_opt phdr_opt fill_opt
// {
// ldlex_popstate ();
@@ -946,12 +950,12 @@ section: NAME // { ldlex_expression(); }
// { 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
// {
@@ -970,7 +974,7 @@ section: NAME // { ldlex_expression(); }
// ldlex_popstate ();
// lang_add_assignment (exp_assign (".", $3, FALSE));
// }
- '{' sec_or_group_p1 '}'
+ LBRACE sec_or_group_p1 RBRACE
| INCLUDE filename
// { ldlex_script (); ldfile_open_command_file($2); }
sec_or_group_p1 END
@@ -986,26 +990,26 @@ type:
;
atype:
- '(' type ')'
+ LPAREN type RPAREN
| /* EMPTY */ // { sectype = normal_section; }
- | '(' ')' // { sectype = normal_section; }
+ | LPAREN RPAREN // { sectype = normal_section; }
;
opt_exp_with_type:
- exp atype ':' // { $$ = $1; }
- | atype ':' // { $$ = (etree_type *)NULL; }
+ 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 '(' exp ')' atype ':' // { $$ = $3; }
- | BIND '(' exp ')' BLOCK '(' exp ')' atype ':'
+ BIND LPAREN exp RPAREN atype COLON // { $$ = $3; }
+ | BIND LPAREN exp RPAREN BLOCK LPAREN exp RPAREN atype COLON
// { $$ = $3; }
;
opt_exp_without_type:
- exp ':' // { $$ = $1; }
- | ':' // { $$ = (etree_type *) NULL; }
+ exp COLON // { $$ = $1; }
+ | COLON // { $$ = (etree_type *) NULL; }
;
opt_nocrossrefs:
@@ -1016,7 +1020,7 @@ opt_nocrossrefs:
;
memspec_opt:
- '>' NAME
+ GT NAME
// { $$ = $2; }
| // { $$ = DEFAULT_MEMORY_REGION; }
;
@@ -1026,7 +1030,7 @@ phdr_opt:
// {
// $$ = NULL;
// }
- | phdr_opt ':' NAME
+ | phdr_opt COLON NAME
// {
// struct lang_output_section_phdr_list *n;
//
@@ -1047,7 +1051,7 @@ overlay_section:
// ldlex_script ();
// lang_enter_overlay_section ($2);
// }
- '{' statement_list_opt '}'
+ LBRACE statement_list_opt RBRACE
// { ldlex_popstate (); ldlex_expression (); }
phdr_opt fill_opt
// {
@@ -1058,7 +1062,7 @@ overlay_section:
;
phdrs:
- PHDRS '{' phdr_list '}'
+ PHDRS LBRACE phdr_list RBRACE
;
phdr_list:
@@ -1069,7 +1073,7 @@ phdr_list:
phdr:
NAME // { ldlex_expression (); }
phdr_type phdr_qualifiers // { ldlex_popstate (); }
- ';'
+ SEMICOLON
// {
// lang_new_phdr ($1, $3, $4.filehdr, $4.phdrs, $4.at,
// $4.flags);
@@ -1082,7 +1086,7 @@ phdr_type:
// $$ = $1;
//
// if ($1->type.node_class == etree_name
-// && $1->type.node_code == NAME)
+// && $1->type.node_code ==name)
// {
// const char *s;
// unsigned int i;
@@ -1138,7 +1142,7 @@ phdr_qualifiers:
// einfo (_("%X%P:%S: PHDRS syntax error at `%s'\n"),
// NULL, $1);
// }
- | AT '(' exp ')' phdr_qualifiers
+ | AT LPAREN exp RPAREN phdr_qualifiers
// {
// $$ = $5;
// $$.at = $3;
@@ -1150,7 +1154,7 @@ phdr_val:
// {
// $$ = NULL;
// }
- | '(' exp ')'
+ | LPAREN exp RPAREN
// {
// $$ = $2;
// }
@@ -1174,11 +1178,11 @@ dynamic_list_nodes:
;
dynamic_list_node:
- '{' dynamic_list_tag '}' ';'
+ LBRACE dynamic_list_tag RBRACE SEMICOLON
;
dynamic_list_tag:
- vers_defns ';'
+ vers_defns SEMICOLON
// {
// lang_append_dynamic_list ($1);
// }
@@ -1204,7 +1208,7 @@ version:
// {
// ldlex_version_script ();
// }
- VERSIONK '{' vers_nodes '}'
+ VERSIONK LBRACE vers_nodes RBRACE
// {
// ldlex_popstate ();
// }
@@ -1216,15 +1220,15 @@ vers_nodes:
;
vers_node:
- '{' vers_tag '}' ';'
+ LBRACE vers_tag RBRACE SEMICOLON
// {
// lang_register_vers_node (NULL, $2, NULL);
// }
- | VERS_TAG '{' vers_tag '}' ';'
+ | VERS_TAG LBRACE vers_tag RBRACE SEMICOLON
// {
// lang_register_vers_node ($1, $3, NULL);
// }
- | VERS_TAG '{' vers_tag '}' verdep ';'
+ | VERS_TAG LBRACE vers_tag RBRACE verdep SEMICOLON
// {
// lang_register_vers_node ($1, $3, $5);
// }
@@ -1246,19 +1250,19 @@ vers_tag:
// {
// $$ = lang_new_vers_node (NULL, NULL);
// }
- | vers_defns ';'
+ | vers_defns SEMICOLON
// {
// $$ = lang_new_vers_node ($1, NULL);
// }
- | GLOBAL ':' vers_defns ';'
+ | GLOBAL COLON vers_defns SEMICOLON
// {
// $$ = lang_new_vers_node ($3, NULL);
// }
- | LOCAL ':' vers_defns ';'
+ | LOCAL COLON vers_defns SEMICOLON
// {
// $$ = lang_new_vers_node (NULL, $3);
// }
- | GLOBAL ':' vers_defns ';' LOCAL ':' vers_defns ';'
+ | GLOBAL COLON vers_defns SEMICOLON LOCAL COLON vers_defns SEMICOLON
// {
// $$ = lang_new_vers_node ($3, $7);
// }
@@ -1269,24 +1273,24 @@ vers_defns:
// {
// $$ = lang_new_vers_pattern (NULL, $1, ldgram_vers_current_lang, FALSE);
// }
- | NAME
+ | NAME
// {
// $$ = lang_new_vers_pattern (NULL, $1, ldgram_vers_current_lang, TRUE);
// }
- | vers_defns ';' VERS_IDENTIFIER
+ | vers_defns SEMICOLON VERS_IDENTIFIER
// {
// $$ = lang_new_vers_pattern ($1, $3, ldgram_vers_current_lang, FALSE);
// }
- | vers_defns ';' NAME
+ | vers_defns SEMICOLON NAME
// {
// $$ = lang_new_vers_pattern ($1, $3, ldgram_vers_current_lang, TRUE);
// }
- | vers_defns ';' EXTERN NAME '{'
+ | vers_defns SEMICOLON EXTERN NAME LBRACE
// {
// $<name>$ = ldgram_vers_current_lang;
// ldgram_vers_current_lang = $4;
// }
- vers_defns opt_semicolon '}'
+ vers_defns opt_semicolon RBRACE
// {
// struct bfd_elf_version_expr *pat;
// for (pat = $7; pat->next != NULL; pat = pat->next);
@@ -1294,12 +1298,12 @@ vers_defns:
// $$ = $7;
// ldgram_vers_current_lang = $<name>6;
// }
- | EXTERN NAME '{'
+ | EXTERN NAME LBRACE
// {
// $<name>$ = ldgram_vers_current_lang;
// ldgram_vers_current_lang = $2;
// }
- vers_defns opt_semicolon '}'
+ vers_defns opt_semicolon RBRACE
// {
// $$ = $5;
// ldgram_vers_current_lang = $<name>4;
@@ -1308,7 +1312,7 @@ vers_defns:
// {
// $$ = lang_new_vers_pattern (NULL, "global", ldgram_vers_current_lang, FALSE);
// }
- | vers_defns ';' GLOBAL
+ | vers_defns SEMICOLON GLOBAL
// {
// $$ = lang_new_vers_pattern ($1, "global", ldgram_vers_current_lang, FALSE);
// }
@@ -1316,7 +1320,7 @@ vers_defns:
// {
// $$ = lang_new_vers_pattern (NULL, "local", ldgram_vers_current_lang, FALSE);
// }
- | vers_defns ';' LOCAL
+ | vers_defns SEMICOLON LOCAL
// {
// $$ = lang_new_vers_pattern ($1, "local", ldgram_vers_current_lang, FALSE);
// }
@@ -1324,7 +1328,7 @@ vers_defns:
// {
// $$ = lang_new_vers_pattern (NULL, "extern", ldgram_vers_current_lang, FALSE);
// }
- | vers_defns ';' EXTERN
+ | vers_defns SEMICOLON EXTERN
// {
// $$ = lang_new_vers_pattern ($1, "extern", ldgram_vers_current_lang, FALSE);
// }
@@ -1332,169 +1336,10 @@ vers_defns:
opt_semicolon:
/* empty */
- | ';'
- ;
-
-//%token <token>
-LBRACE : '{';
-RBRACE : '}';
-
-// <integer>
-// <token> assign_op atype attributes_opt sect_constraint opt_align_with_input
-// <name> filename
-//%type <versyms> vers_defns
-//%type <versnode> vers_tag
-//%type <deflist> verdep
-
-ABSOLUTE : 'ABSOLUTE';
-ADDR : 'ADDR';
-AFTER : 'AFTER';
-ALIAS : 'ALIAS';
-ALIGN : 'ALIGN';
-ALIGN_K : 'ALIGN';
-ALIGNMOD : 'ALIGNMOD';
-ALIGNOF : 'ALIGNOF';
-ALIGN_WITH_INPUT : 'ALIGN_WITH_INPUT';
-AS_NEEDED : 'AS_NEEDED';
-ASSERT_K : 'ASSERT';
-AT : 'AT';
-BASE : 'BASE';
-BEFORE : 'BEFORE';
-BIND : 'BIND';
-BLOCK : 'BLOCK';
-BYTE : 'BYTE';
-CASE : 'CASE';
-CHIP : 'CHIP';
-CONSTANT : 'CONSTANT';
-CONSTRUCTORS : 'CONSTRUCTORS';
-COPY : 'COPY';
-CREATE_OBJECT_SYMBOLS : 'CREATE_OBJECT_SYMBOLS';
-DATA_SEGMENT_ALIGN : 'DATA_SEGMENT_ALIGN';
-DATA_SEGMENT : 'DATA_SEGMENT';
-DATA_SEGMENT_END : 'DATA_SEGMENT_END';
-DATA_SEGMENT_RELRO_END : 'DATA_SEGMENT_RELRO_END';
-DEFINED : 'DEFINED';
-DEFSYMEND : 'DEFSYMEND';
-DSECT : 'DSECT';
-ENDWORD : 'ENDWORD';
-ENTRY : 'ENTRY';
-EXCLUDE_FILE : 'EXCLUDE_FILE';
-EXTERN : 'EXTERN';
-FILL : 'FILL';
-FLOAT : 'FLOAT';
-FORCE_COMMON_ALLOCATION : 'FORCE_COMMON_ALLOCATION';
-FORMAT : 'FORMAT';
-GLOBAL : 'GLOBAL';
-GROUP : 'GROUP';
-HIDDEN_ : 'HIDDEN';
-HLL : 'HLL';
-INCLUDE : 'INCLUDE';
-INFO : 'INFO';
-INHIBIT_COMMON_ALLOCATION : 'INHIBIT_COMMON_ALLOCATION';
-//INPUT_DEFSYM : 'INPUT_DEFSYM';
-//INPUT_DYNAMIC_LIST : 'INPUT_DYNAMIC_LIST';
-INPUT : 'INPUT';
-//INPUT_MRI_SCRIPT : 'INPUT_MRI_SCRIPT';
-//INPUT_SCRIPT : 'INPUT_SCRIPT';
-//INPUT_SECTION_FLAGS : 'INPUT_SECTION_FLAGS';
-//INPUT_VERSION_SCRIPT : 'INPUT_VERSION_SCRIPT';
-INSERT_K : 'INSERT';
-KEEP : 'KEEP';
-LD_FEATURE : 'LD_FEATURE';
-LENGTH : 'LENGTH';
-LIST : 'LIST';
-LOADADDR : 'LOADADDR';
-LOAD : 'LOAD';
-LOCAL : 'LOCAL';
-LOG2CEIL : 'LOG2CEIL';
-LONG : 'LONG';
-MAP : 'MAP';
-MAX_K : 'MAX';
-MEMORY : 'MEMORY';
-MIN_K : 'MIN';
-NAMEWORD : 'NAMEWORD';
-NEWLINE : 'NEWLINE';
-NEXT : 'NEXT';
-NOCROSSREFS : 'NOCROSSREFS';
-NOCROSSREFS_TO : 'NOCROSSREFS_TO';
-NOFLOAT : 'NOFLOAT';
-NOLOAD : 'NOLOAD';
-ONLY_IF_RO : 'ONLY_IF_RO';
-ONLY_IF_RW : 'ONLY_IF_RW';
-ORDER : 'ORDER';
-ORIGIN : 'ORIGIN'; // TODO: or 'org' or 'o'.
-OUTPUT_ARCH : 'OUTPUT_ARCH';
-OUTPUT_FORMAT : 'OUTPUT_FORMAT';
-OUTPUT : 'OUTPUT';
-OVERLAY : 'OVERLAY';
-PHDRS : 'PHDRS';
-PROVIDE_HIDDEN : 'PROVIDE_HIDDEN';
-PROVIDE : 'PROVIDE';
-PUBLIC : 'PUBLIC';
-QUAD : 'QUAD';
-REGION_ALIAS : 'REGION_ALIAS';
-REL : 'REL';
-SEARCH_DIR : 'SEARCH_DIR';
-SECTIONS : 'SECTIONS';
-SECT : 'SECT';
-SEGMENT_START : 'SEGMENT_START';
-SHORT : 'SHORT';
-SIZEOF_HEADERS : 'SIZEOF_HEADERS';
-SIZEOF : 'SIZEOF';
-SORT_BY_ALIGNMENT : 'SORT_BY_ALIGNMENT';
-SORT_BY_INIT_PRIORITY : 'SORT_BY_INIT_PRIORITY';
-SORT_BY_NAME : 'SORT_BY_NAME';
-SORT_NONE : 'SORT_NONE';
-SPECIAL : 'SPECIAL';
-SQUAD : 'SQUAD';
-START : 'START';
-STARTUP : 'STARTUP';
-SUBALIGN : 'SUBALIGN';
-SYSLIB : 'SYSLIB';
-TARGET_K : 'TARGET';
-TRUNCATE : 'TRUNCATE';
-VERS_IDENTIFIER : 'VERS_IDENTIFIER';
-VERSIONK : 'VERSIONK';
-VERS_TAG : 'VERS_TAG';
-
-/*
-Names are very liberal, they can be full strings and start with a dot.
-*/
+ | SEMICOLON
+ ;
-NAME : [\._a-zA-Z][_a-zA-Z0-9]*;
-
-// TODO: ld supports some really fancy expressions here, like "0101010b", "ffH", "ffx", "$Aa" etc
-//INT : '0x' [0-9a-fA-F]+
-// | [0-9]+;
-INT : INT_NUMBER INT_SIZE?;
-INT_NUMBER : INT_HEX
- | INT_DECIMAL;
-INT_HEX : '0x' [0-9a-fA-F]+;
-INT_DECIMAL : [0-9]+;
-INT_SIZE : 'M' | 'm' | 'K' | 'k';
-
-END : 'END';
-
-LNAME : '-l' NAME;
-PLUSEQ : '+=';
-MINUSEQ : '-=';
-MULTEQ : '*=';
-DIVEQ : '/=';
-LSHIFTEQ : '<<=';
-RSHIFTEQ : '>>=';
-ANDEQ : '&=';
-OREQ : '|=';
-LSHIFT : '<<';
-RSHIFT : '>>';
-EQ : '=';
-NE : '!=';
-LE : '<=';
-GE : '>=';
-ANDAND : '&&';
-OROR : '||';
-
-BlockComment
- : '/*' .*? '*/' -> skip
- ;
+//name
+// : NAME;
-WS : [ \t\r\n]+ -> skip ;
+string: STRING_ANY*;
diff --git a/cmake/elfinfo/g4.sh b/cmake/elfinfo/g4.sh
new file mode 100755
index 0000000..2f33070
--- /dev/null
+++ b/cmake/elfinfo/g4.sh
@@ -0,0 +1,11 @@
+#!/bin/bash
+
+url="http://repo1.maven.org/maven2/org/antlr/antlr4/4.5.3/antlr4-4.5.3.jar"
+jar="$(basename $url)"
+
+if [[ ! -r "$jar" ]]
+then
+ wget "$url"
+fi
+
+exec java -cp "$jar" org.antlr.v4.Tool "$@"
diff --git a/cmake/elfinfo/pom.xml b/cmake/elfinfo/pom.xml
index bb46e6f..60511b0 100644
--- a/cmake/elfinfo/pom.xml
+++ b/cmake/elfinfo/pom.xml
@@ -7,19 +7,28 @@
<dependency>
<groupId>org.antlr</groupId>
<artifactId>antlr4</artifactId>
- <version>4.5.3</version>
+ <version>${antlr4-runtime.version}</version>
</dependency>
<dependency>
<groupId>org.antlr</groupId>
<artifactId>antlr4-runtime</artifactId>
- <version>4.5.3</version>
+ <version>${antlr4-runtime.version}</version>
</dependency>
<dependency>
<groupId>com.google.code.findbugs</groupId>
<artifactId>jsr305</artifactId>
<version>3.0.1</version>
</dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>4.12</version>
+ <scope>test</scope>
+ </dependency>
</dependencies>
+ <properties>
+ <antlr4-runtime.version>4.5.3</antlr4-runtime.version>
+ </properties>
<build>
<plugins>
<plugin>
@@ -29,6 +38,50 @@
<target>1.8</target>
</configuration>
</plugin>
+ <plugin>
+ <groupId>org.antlr</groupId>
+ <artifactId>antlr4-maven-plugin</artifactId>
+ <version>${antlr4-runtime.version}</version>
+ <executions>
+ <execution>
+ <id>gnu</id>
+ <goals>
+ <goal>antlr4</goal>
+ </goals>
+ <configuration>
+ <arguments>
+ <argument>-package</argument>
+ <argument>io.trygvis.ld.antlr</argument>
+ </arguments>
+ <includes>
+ <include>GnuLd*.g4</include>
+ </includes>
+ <sourceDirectory>.</sourceDirectory>
+ <outputDirectory>target/generated-sources/antlr4/io/trygvis/ld/antlr</outputDirectory>
+ </configuration>
+ </execution>
+ <execution>
+ <id>test1</id>
+ <goals>
+ <goal>antlr4</goal>
+ </goals>
+ <configuration>
+ <arguments>
+ <argument>-package</argument>
+ <argument>io.trygvis.ld.test1</argument>
+ </arguments>
+ <includes>
+ <include>**/Test1*.g4</include>
+ </includes>
+ <outputDirectory>target/generated-sources/antlr4/io/trygvis/ld/test1</outputDirectory>
+ </configuration>
+ </execution>
+ </executions>
+ <configuration>
+ <visitor>true</visitor>
+ <outputDirectory>target/generated-sources/antlr4</outputDirectory>
+ </configuration>
+ </plugin>
</plugins>
</build>
</project>
diff --git a/cmake/elfinfo/src/main/antlr4/Test1Lexer.g4 b/cmake/elfinfo/src/main/antlr4/Test1Lexer.g4
new file mode 100644
index 0000000..142229d
--- /dev/null
+++ b/cmake/elfinfo/src/main/antlr4/Test1Lexer.g4
@@ -0,0 +1,22 @@
+lexer grammar Test1Lexer;
+
+channels {
+ WHITESPACE_CHANNEL
+}
+
+NAME : [a-z]+;
+
+// Characters
+C_PLUS : '+';
+C_MINUS : '-';
+C_QUOTE : '"' -> skip, pushMode(STRING);
+
+//SPACE : [ ];
+
+WS
+ : [ \t\r\n]+ -> channel(WHITESPACE_CHANNEL)
+ ;
+
+mode STRING;
+STRING_ANY : ~'"';
+STRING_END_QUOTE : '"' -> skip, popMode;
diff --git a/cmake/elfinfo/src/main/antlr4/Test1Parser.g4 b/cmake/elfinfo/src/main/antlr4/Test1Parser.g4
new file mode 100644
index 0000000..affdfe5
--- /dev/null
+++ b/cmake/elfinfo/src/main/antlr4/Test1Parser.g4
@@ -0,0 +1,23 @@
+parser grammar Test1Parser;
+
+options {
+ tokenVocab = Test1Lexer;
+}
+
+name
+ : NAME
+ | STRING_ANY*
+ ;
+
+file
+ : stmt*
+ ;
+
+stmt
+ : expr
+ ;
+
+expr
+ : name C_PLUS name
+ | name C_MINUS name
+ ;
diff --git a/cmake/elfinfo/src/main/java/io/trygvis/ld/CollectingErrorListener.java b/cmake/elfinfo/src/main/java/io/trygvis/ld/CollectingErrorListener.java
new file mode 100644
index 0000000..968a02b
--- /dev/null
+++ b/cmake/elfinfo/src/main/java/io/trygvis/ld/CollectingErrorListener.java
@@ -0,0 +1,17 @@
+package io.trygvis.ld;
+
+import org.antlr.v4.runtime.BaseErrorListener;
+import org.antlr.v4.runtime.RecognitionException;
+import org.antlr.v4.runtime.Recognizer;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class CollectingErrorListener extends BaseErrorListener {
+ public final List<String> errors = new ArrayList<>();
+
+ public void syntaxError(Recognizer<?, ?> recognizer, Object offendingSymbol, int line, int charPositionInLine, String msg, RecognitionException e) {
+ String s = line + ":" + charPositionInLine + " " + msg;
+ errors.add(s);
+ }
+}
diff --git a/cmake/elfinfo/src/main/java/io/trygvis/ld/LdScript.java b/cmake/elfinfo/src/main/java/io/trygvis/ld/LdScript.java
index f827a8b..f3c93ac 100644
--- a/cmake/elfinfo/src/main/java/io/trygvis/ld/LdScript.java
+++ b/cmake/elfinfo/src/main/java/io/trygvis/ld/LdScript.java
@@ -1,12 +1,14 @@
package io.trygvis.ld;
-import io.trygvis.ld.antlr.GnuLdBaseVisitor;
import io.trygvis.ld.antlr.GnuLdLexer;
import io.trygvis.ld.antlr.GnuLdParser;
+import io.trygvis.ld.antlr.GnuLdParserBaseVisitor;
import org.antlr.v4.runtime.ANTLRFileStream;
import org.antlr.v4.runtime.BufferedTokenStream;
+import org.antlr.v4.runtime.ConsoleErrorListener;
import org.antlr.v4.runtime.tree.ParseTreeProperty;
+import java.io.File;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.HashSet;
@@ -15,6 +17,12 @@ import java.util.Set;
public class LdScript {
+ public final List<MemoryArea> memoryAreas;
+
+ public LdScript(List<MemoryArea> memoryAreas) {
+ this.memoryAreas = memoryAreas;
+ }
+
public enum MemoryAttribute {
R, W, X, A, I,
}
@@ -76,39 +84,31 @@ public class LdScript {
String name;
}
- public static void main(String[] args) throws Exception {
- try {
- work(args);
- } catch (Exception e) {
- e.printStackTrace(System.out);
- }
- }
-
- private static void work(String[] args) throws Exception {
- args = new String[]{"lds/d2000.ld"};
+ public static LdScript parse(File path) throws Exception {
+ GnuLdLexer lexer = new GnuLdLexer(new ANTLRFileStream(path.getAbsolutePath()));
+ BufferedTokenStream tokens = new BufferedTokenStream(lexer);
+ GnuLdParser parser = new GnuLdParser(tokens);
+ parser.setBuildParseTree(true);
+ parser.removeErrorListeners();
+ ConsoleErrorListener errorListener = new ConsoleErrorListener();
+ parser.addErrorListener(errorListener);
+ CollectingErrorListener collectingErrorListener = new CollectingErrorListener();
+ parser.addErrorListener(collectingErrorListener);
- GnuLdLexer lexer = new GnuLdLexer(new ANTLRFileStream(args[0]));
- GnuLdParser parser = new GnuLdParser(new BufferedTokenStream(lexer));
+ GnuLdParser.FileContext file = parser.file();
-// ElfInfoGnuLdBaseListener listener = new ElfInfoGnuLdBaseListener();
-// parser.addParseListener(listener);
-//
-// parser.file();
-//
-// for (Section section : listener.sections) {
-// System.out.println("section.name = " + section.name);
-// }
+ if (parser.getNumberOfSyntaxErrors() > 0) {
+ throw new ParseErrorException(lexer, tokens, parser, collectingErrorListener.errors
+ );
+ }
ElfinfoGnuLdBaseVisitor visitor = new ElfinfoGnuLdBaseVisitor();
- visitor.visit(parser.file());
+ visitor.visit(file);
- System.out.println("--------------------------------------------------------");
- for (MemoryArea area : visitor.memoryAreas) {
- System.out.println(" " + area.name + "(" + area.prettyAttributes() + ") : ORIGIN = " + area.prettyOrigin() + ", LENGTH=" + area.prettyLength());
- }
+ return new LdScript(visitor.memoryAreas);
}
- private static class ElfinfoExprGnuLdBaseVisitor extends GnuLdBaseVisitor<ElfinfoExprGnuLdBaseVisitor> {
+ private static class ElfinfoExprGnuLdBaseVisitor extends GnuLdParserBaseVisitor<ElfinfoExprGnuLdBaseVisitor> {
private BigInteger value;
private ParseTreeProperty<BigInteger> es = new ParseTreeProperty<>();
@@ -227,7 +227,7 @@ public class LdScript {
}
@Override
- public ElfinfoExprGnuLdBaseVisitor visitExpAlign2(GnuLdParser.ExpAlign2Context ctx) {
+ public ElfinfoExprGnuLdBaseVisitor visitExpAlignK(GnuLdParser.ExpAlignKContext ctx) {
return visitChildren(ctx);
}
@@ -416,7 +416,7 @@ public class LdScript {
}
}
- private static class ElfinfoGnuLdBaseVisitor extends GnuLdBaseVisitor<ElfinfoGnuLdBaseVisitor> {
+ public static class ElfinfoGnuLdBaseVisitor extends GnuLdParserBaseVisitor<ElfinfoGnuLdBaseVisitor> {
public List<MemoryArea> memoryAreas = new ArrayList<>();
public List<Section> sections = new ArrayList<>();
@@ -473,6 +473,7 @@ public class LdScript {
if (!attributes.isEmpty()) {
throw new RuntimeException("Attributes for memory areas can only be attributesInverted (with '!') as the first character in a specification; foo(!rw), not foo(x!rw).");
}
+// String name = ctx.name().getText();
String name = ctx.NAME().getText();
System.out.println("ctx.ATTRIBUTE().getText() = " + name);
@@ -480,4 +481,18 @@ public class LdScript {
return visitChildren(ctx);
}
}
+
+ public static class ParseErrorException extends Exception {
+ public final GnuLdLexer lexer;
+ public final BufferedTokenStream tokens;
+ public final GnuLdParser parser;
+ public final List<String> errors;
+
+ public ParseErrorException(GnuLdLexer lexer, BufferedTokenStream tokens, GnuLdParser parser, List<String> errors) {
+ this.lexer = lexer;
+ this.tokens = tokens;
+ this.parser = parser;
+ this.errors = errors;
+ }
+ }
}
diff --git a/cmake/elfinfo/src/main/java/io/trygvis/ld/StringGnuLdVisitor.java b/cmake/elfinfo/src/main/java/io/trygvis/ld/StringGnuLdVisitor.java
new file mode 100644
index 0000000..a975497
--- /dev/null
+++ b/cmake/elfinfo/src/main/java/io/trygvis/ld/StringGnuLdVisitor.java
@@ -0,0 +1,59 @@
+package io.trygvis.ld;
+
+import io.trygvis.ld.antlr.GnuLdParserBaseVisitor;
+import io.trygvis.ld.antlr.GnuLdParser;
+import org.antlr.v4.runtime.tree.ParseTree;
+
+import java.util.List;
+
+class StringGnuLdVisitor extends GnuLdParserBaseVisitor<String> {
+
+// public static String parseName(GnuLdParser.NameContext ctx) {
+// return "";
+// }
+
+ /*
+ public static String parseName(GnuLdParser.NameContext ctx) {
+ StringGnuLdVisitor v = new StringGnuLdVisitor();
+ return v.visit(ctx);
+ }
+
+ private StringBuilder string = new StringBuilder();
+
+ @Override
+ public String visitNamePlain(GnuLdParser.NamePlainContext ctx) {
+ System.out.println("NameTest.visitNamePlain");
+ String s = ctx.NAME().getText();
+ string.append(s);
+ return s;
+ }
+
+// @Override
+// public String visitName_or_space(GnuLdParser.Name_or_spaceContext ctx) {
+// System.out.println("StringGnuLdBaseVisitor.visitName_or_space");
+//
+// TerminalNode name = ctx.NAME();
+// String s = name != null ? name.getText() : " ";
+// string.append(s);
+// return s;
+// }
+
+ @Override
+ public String visitNameQuoted(GnuLdParser.NameQuotedContext ctx) {
+ System.out.println("StringGnuLdBaseVisitor.visitNameQuoted");
+ List<ParseTree> children = ctx.children;
+ System.out.println("children.size()) = " + children.size());
+
+ String s = "";
+ for (int i = 1; i < children.size() - 1; i++) {
+ ParseTree part = children.get(i);
+ System.out.println("part.getText() = " + part.getText());
+ s += part.getText();
+ }
+
+ return s;
+//
+// return visitChildren(ctx);
+ }
+ */
+}
diff --git a/cmake/elfinfo/src/main/test/io/trygvis/ld/FullScriptsTest.java b/cmake/elfinfo/src/main/test/io/trygvis/ld/FullScriptsTest.java
new file mode 100644
index 0000000..1452f1f
--- /dev/null
+++ b/cmake/elfinfo/src/main/test/io/trygvis/ld/FullScriptsTest.java
@@ -0,0 +1,34 @@
+package io.trygvis.ld;
+
+import io.trygvis.ld.test1.Test1Test;
+import org.junit.Test;
+
+import java.io.File;
+
+public class FullScriptsTest {
+
+ @Test
+ public void testD2000() throws Exception {
+ fullScript2("lds/d2000.ld");
+ }
+
+ @Test
+ public void testStm32() throws Exception {
+ fullScript2("lds/stm32.ld");
+ }
+
+ private void fullScript2(String fileName) throws Exception {
+ try {
+ LdScript script = LdScript.parse(new File(fileName));
+
+ System.out.println("--------------------------------------------------------");
+ for (LdScript.MemoryArea area : script.memoryAreas) {
+ System.out.println(" " + area.name + "(" + area.prettyAttributes() + ") : ORIGIN = " + area.prettyOrigin() + ", LENGTH=" + area.prettyLength());
+ }
+ } catch (LdScript.ParseErrorException e) {
+ Test1Test.showTokens(e.tokens, e.parser);
+ System.out.println("Got " + e.errors.size() + " errors:");
+ e.errors.forEach(System.out::println);
+ }
+ }
+}
diff --git a/cmake/elfinfo/src/main/test/io/trygvis/ld/InputSectionSpecTest.java b/cmake/elfinfo/src/main/test/io/trygvis/ld/InputSectionSpecTest.java
new file mode 100644
index 0000000..2950061
--- /dev/null
+++ b/cmake/elfinfo/src/main/test/io/trygvis/ld/InputSectionSpecTest.java
@@ -0,0 +1,38 @@
+package io.trygvis.ld;
+
+import io.trygvis.ld.antlr.GnuLdLexer;
+import io.trygvis.ld.antlr.GnuLdParser;
+import org.antlr.v4.runtime.ANTLRInputStream;
+import org.antlr.v4.runtime.CommonTokenStream;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+public class InputSectionSpecTest {
+ @Test
+ public void testName1() throws Exception {
+ a("*(.text)", "(input_section_spec (input_section_spec_no_keep (wildcard_spec (wildcard_name *)) ( (file_name_list (wildcard_spec (wildcard_name .text))) )))");
+ }
+
+ // This doesn't feel right
+ @Test
+ public void testName2() throws Exception {
+ a("*(.text.*)", "(input_section_spec (input_section_spec_no_keep (wildcard_spec (wildcard_name *)) ( (file_name_list (file_name_list (wildcard_spec (wildcard_name .text.))) opt_comma (wildcard_spec (wildcard_name *))) )))");
+ }
+
+ @Test
+ public void testName3() throws Exception {
+ a("KEEP(*/init_high.cpp.obj(.isr_vectors))", "(input_section_spec KEEP ( (input_section_spec_no_keep (wildcard_spec (wildcard_name *)) / init_high.cpp.obj ( .isr_vectors) ))");
+ }
+
+ private void a(String input, String expected) {
+ GnuLdParser parser = new GnuLdParser(new CommonTokenStream(new GnuLdLexer(new ANTLRInputStream(input))));
+ parser.setBuildParseTree(true);
+ parser.removeErrorListeners();
+ parser.addErrorListener(new SystemOutReportingErrorListener(input));
+ GnuLdParser.Input_section_specContext input_section_spec = parser.input_section_spec();
+
+ assertEquals(input, expected, input_section_spec.toStringTree(parser));
+ assertEquals(0, parser.getNumberOfSyntaxErrors());
+ }
+}
diff --git a/cmake/elfinfo/src/main/test/io/trygvis/ld/NameTest.java b/cmake/elfinfo/src/main/test/io/trygvis/ld/NameTest.java
new file mode 100644
index 0000000..8d7502f
--- /dev/null
+++ b/cmake/elfinfo/src/main/test/io/trygvis/ld/NameTest.java
@@ -0,0 +1,50 @@
+package io.trygvis.ld;
+
+import io.trygvis.ld.antlr.GnuLdLexer;
+import io.trygvis.ld.antlr.GnuLdParser;
+import org.antlr.v4.runtime.ANTLRInputStream;
+import org.antlr.v4.runtime.CommonTokenStream;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+public class NameTest {
+ @Test
+ public void testName1() throws Exception {
+ a("foo", "foo");
+ }
+
+ @Test
+ public void testName2() throws Exception {
+ a("\"foo bar\"", "foo bar");
+ }
+
+ // TODO: not really expected
+ @Test
+ public void testName3() throws Exception {
+ a("\"foo bar\"", "foo bar");
+ }
+
+ private void a(String input, String expected) {
+ /*
+ CommonTokenStream tokens = new CommonTokenStream(new GnuLdLexer(new ANTLRInputStream(input)));
+ tokens.fill();
+ for (Object tok : tokens.getTokens()) {
+ System.out.println(tok);
+ }
+ GnuLdParser parser = new GnuLdParser(tokens);
+
+// StringGnuLdVisitor visitor = new StringGnuLdVisitor();
+ GnuLdParser.NameContext name = parser.name();
+
+ System.out.println("Input : |" + input + "|");
+ System.out.println("String tree: " + name.toStringTree(parser));
+
+// visitor.visit(name);
+ String actual = StringGnuLdVisitor.parseName(name);
+
+ parser.setTrace(true);
+ assertEquals(input + "\n" + name.toStringTree(), expected, actual);
+ */
+ }
+}
diff --git a/cmake/elfinfo/src/main/test/io/trygvis/ld/SystemOutReportingErrorListener.java b/cmake/elfinfo/src/main/test/io/trygvis/ld/SystemOutReportingErrorListener.java
new file mode 100644
index 0000000..c21a2e2
--- /dev/null
+++ b/cmake/elfinfo/src/main/test/io/trygvis/ld/SystemOutReportingErrorListener.java
@@ -0,0 +1,32 @@
+package io.trygvis.ld;
+
+import org.antlr.v4.runtime.BaseErrorListener;
+import org.antlr.v4.runtime.RecognitionException;
+import org.antlr.v4.runtime.Recognizer;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+public class SystemOutReportingErrorListener extends BaseErrorListener {
+ @Nullable
+ private final String input;
+
+ public SystemOutReportingErrorListener(@Nonnull String input) {
+ this.input = input;
+ }
+
+ public SystemOutReportingErrorListener() {
+ input = null;
+ }
+
+ public void syntaxError(Recognizer<?, ?> recognizer, Object offendingSymbol, int line, int charPositionInLine, String msg, RecognitionException e) {
+ System.out.println("line " + line + ":" + charPositionInLine + " " + msg);
+ if (input != null) {
+ System.out.println(input);
+ for (int i = 1; i < charPositionInLine; i++) {
+ System.out.print(' ');
+ }
+ }
+ System.out.println('^');
+ }
+}
diff --git a/cmake/elfinfo/src/main/test/io/trygvis/ld/test1/Test1Test.java b/cmake/elfinfo/src/main/test/io/trygvis/ld/test1/Test1Test.java
new file mode 100644
index 0000000..ca3f49a
--- /dev/null
+++ b/cmake/elfinfo/src/main/test/io/trygvis/ld/test1/Test1Test.java
@@ -0,0 +1,102 @@
+package io.trygvis.ld.test1;
+
+import org.antlr.v4.runtime.ANTLRInputStream;
+import org.antlr.v4.runtime.BufferedTokenStream;
+import org.antlr.v4.runtime.CommonToken;
+import org.antlr.v4.runtime.CommonTokenStream;
+import org.antlr.v4.runtime.Parser;
+import org.antlr.v4.runtime.Token;
+import org.junit.Test;
+
+import javax.annotation.Nonnull;
+
+import static org.junit.Assert.assertEquals;
+
+public class Test1Test {
+
+ @Test
+ public void test1() {
+ name("foo", "foo");
+ }
+
+ @Test
+ public void test2() {
+ name("\"foo bar\"", "foo bar");
+ }
+
+ private void name(String input, String expected) {
+ Test1Parser parser = load(input);
+
+ Test1Parser.NameContext name = parser.name();
+ System.out.println("String tree: " + name.toStringTree(parser));
+
+ String actual = name.getText();
+ assertEquals(input + "\n" + name.toStringTree(parser), expected, actual);
+ }
+
+ @Test
+ public void expr1() {
+ expr("a + b", "(expr (name a) + (name b))");
+ }
+
+ @Test
+ public void expr2() {
+ expr("\"foo bar\" + b", "(expr (name f o o b a r) + (name b))");
+ }
+
+ @Test
+ public void expr3() {
+ expr("\n\n\r\n\t\"foo bar\" + b\r\r\t", "(expr (name f o o b a r) + (name b))");
+ }
+
+ private void expr(String input, String expected) {
+ Test1Parser parser = load(input);
+
+ Test1Parser.ExprContext expr = parser.expr();
+ String stringTree = expr.toStringTree(parser);
+
+ assertEquals(expected, stringTree);
+ }
+
+ @Nonnull
+ private Test1Parser load(String input) {
+ System.out.println("Input : |" + input + "|");
+ CommonTokenStream tokens = new CommonTokenStream(new Test1Lexer(new ANTLRInputStream(input)));
+ Test1Parser parser = new Test1Parser(tokens);
+ parser.setBuildParseTree(true);
+ parser.setTrace(true);
+
+ tokens.fill();
+ showTokens(tokens, parser);
+ return parser;
+ }
+
+ public static void showTokens(BufferedTokenStream tokens, Parser parser) {
+ for (Token tok : tokens.getTokens()) {
+ String s;
+ if (tok instanceof CommonToken) {
+ CommonToken t = (CommonToken) tok;
+
+ String channelStr = "";
+ if (t.getChannel() > 0) {
+ channelStr = ",channel=" + t.getChannel();
+ }
+
+ String txt = t.getText();
+ if (txt != null) {
+ txt = txt.replace("\n", "\\n");
+ txt = txt.replace("\r", "\\r");
+ txt = txt.replace("\t", "\\t");
+ } else {
+ txt = "<no text>";
+ }
+
+ String type = parser.getVocabulary().getDisplayName(t.getType());
+ s = "[@" + t.getTokenIndex() + "," + t.getStartIndex() + ":" + t.getStopIndex() + "=\'" + txt + "\',<" + type + ">" + channelStr + "," + t.getLine() + ":" + t.getCharPositionInLine() + "]";
+ } else {
+ s = tok.toString();
+ }
+ System.out.println(s);
+ }
+ }
+}