summaryrefslogtreecommitdiff
path: root/support/splint/examples/ld/ldgram.w
diff options
context:
space:
mode:
Diffstat (limited to 'support/splint/examples/ld/ldgram.w')
-rw-r--r--support/splint/examples/ld/ldgram.w1083
1 files changed, 1083 insertions, 0 deletions
diff --git a/support/splint/examples/ld/ldgram.w b/support/splint/examples/ld/ldgram.w
new file mode 100644
index 0000000000..4fb9a9a876
--- /dev/null
+++ b/support/splint/examples/ld/ldgram.w
@@ -0,0 +1,1083 @@
+@q Copyright 2012-2015 Alexander Shibakov@>
+@q Copyright 2002-2014 Free Software Foundation, Inc.@>
+@q This file is part of SPLinT@>
+
+@q SPLinT is free software: you can redistribute it and/or modify@>
+@q it under the terms of the GNU General Public License as published by@>
+@q the Free Software Foundation, either version 3 of the License, or@>
+@q (at your option) any later version.@>
+
+@q SPLinT is distributed in the hope that it will be useful,@>
+@q but WITHOUT ANY WARRANTY; without even the implied warranty of@>
+@q MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the@>
+@q GNU General Public License for more details.@>
+
+@q You should have received a copy of the GNU General Public License@>
+@q along with SPLinT. If not, see <http://www.gnu.org/licenses/>.@>
+
+@** The parser.
+\ifx\parsernamespace\UNDEFINED
+ \def\tokendeffile{ldp.tok}%
+ \input ldman.sty
+ \input limbo.sty
+ \input dcols.sty
+ \setupfootnotes
+ \def\MRI{}
+ \def\ld{}
+\fi
+\immediate\openout\exampletable=\jobname.exl\relax%
+The outline of the grammar file below does not reveal anything unusual
+in the general layout of \ld\ grammar. The first section lists all the
+token definitions, \prodstyle{\%union} styles, and some \Cee\
+code. The original comments that come with the grammar file of the
+linker have been mostly left intact. They are typeset in {\it
+italics\/} to make them easy to recognize.
+
+@s TeX_ TeX
+@s TeXa TeX
+@s TeXb TeX
+@s TeXf TeX
+@s TeXfo TeX
+@s TeXao TeX
+
+@(ldp.yy@>=
+@G Switch to generic mode.
+%{@> @<\ld\ parser \Cee\ preamble@> @=%}
+ @> @<\ld\ parser \bison\ options@> @=
+%union {@> @<Union of grammar parser types@> @=}
+%{@> @<\ld\ parser \Cee\ postamble@> @=%}
+ @> @<Token and type declarations@> @=
+%%
+ @> @<\ld\ parser productions@> @=
+%%
+@g
+
+@ Among the options listed in this section, \prodstyle{\%token-table}
+is the most critical for the proper operation of the parser and must be enabled
+to supply the token information to the lexer (the traditional way
+of passing this information along is to use a \Cee\ header file with
+the appropriate definitions). The start symbol does not have to be
+given explicitly and can be indicated by listing the appropriate rules
+at the beginning.
+
+Most other sections of the grammar file, with the exception of the
+rules are either empty or hold placeholder values. The functionality
+provided by the code in these sections in the case of a \Cee\ parser
+is supplied by the \TeX\ macros in \.{ldman.sty}.
+@<\ld\ parser \bison\ options@>=
+@G
+%token-table
+%debug
+%start script_file
+@g
+
+@ @<\ld\ parser \Cee\ preamble@>=
+
+@ @<Union of grammar parser types@>=
+
+@ @<\ld\ parser \Cee\ postamble@>=
+#define YYPRINT(file, type, value) yyprint (file, type, value)
+ static void yyprint (FILE *file, int type, YYSTYPE value){}
+
+@ @<\ld\ parser productions@>=
+ @<\GNU\ \ld\ script rules@>@;
+ @<Grammar rules@>@;
+
+@ The tokens are declared first. This section is also used to supply
+numerical token values to the lexer by the original parser, as well as
+the bootstrapping phase of the typesetting parser. Unlike the native (\Cee) parser for
+\ld\ the typesetting parser has no need for the type of each token
+(rather, the type consistency is based on the weak dynamic type system
+coded in \.{yyunion.sty} and \.{ldunion.sy}). Thus all the tokens used
+by the \ld\ parser are put in a single list.
+@<Token and type declarations@>=
+@G
+%token INT
+%token NAME LNAME
+%token END
+%token ALIGN_K BLOCK BIND QUAD SQUAD LONG SHORT BYTE
+%token SECTIONS PHDRS INSERT_K AFTER BEFORE
+%token DATA_SEGMENT_ALIGN DATA_SEGMENT_RELRO_END DATA_SEGMENT_END
+%token SORT_BY_NAME SORT_BY_ALIGNMENT SORT_NONE
+%token SORT_BY_INIT_PRIORITY
+%token '{' '}'
+%token SIZEOF_HEADERS OUTPUT_FORMAT FORCE_COMMON_ALLOCATION OUTPUT_ARCH
+%token INHIBIT_COMMON_ALLOCATION
+%token SEGMENT_START
+%token INCLUDE
+%token MEMORY
+%token REGION_ALIAS
+%token LD_FEATURE
+%token NOLOAD DSECT COPY INFO OVERLAY
+%token DEFINED TARGET_K SEARCH_DIR MAP ENTRY
+%token NEXT
+%token SIZEOF ALIGNOF ADDR LOADADDR MAX_K MIN_K
+%token STARTUP HLL SYSLIB FLOAT NOFLOAT NOCROSSREFS
+%token ORIGIN FILL
+%token LENGTH CREATE_OBJECT_SYMBOLS INPUT GROUP OUTPUT CONSTRUCTORS
+%token ALIGNMOD AT SUBALIGN HIDDEN PROVIDE PROVIDE_HIDDEN AS_NEEDED
+%token CHIP LIST SECT ABSOLUTE LOAD NEWLINE ENDWORD ORDER NAMEWORD ASSERT_K
+%token LOG2CEIL FORMAT PUBLIC DEFSYMEND BASE ALIAS TRUNCATE REL
+%token INPUT_SCRIPT INPUT_MRI_SCRIPT INPUT_DEFSYM CASE EXTERN START
+%token VERS_TAG VERS_IDENTIFIER
+%token GLOBAL LOCAL VERSIONK INPUT_VERSION_SCRIPT
+%token KEEP ONLY_IF_RO ONLY_IF_RW SPECIAL INPUT_SECTION_FLAGS ALIGN_WITH_INPUT
+%token EXCLUDE_FILE
+%token CONSTANT
+%token INPUT_DYNAMIC_LIST
+%right PLUSEQ MINUSEQ MULTEQ DIVEQ '=' LSHIFTEQ RSHIFTEQ ANDEQ OREQ '?' ':' UNARY
+%left OROR ANDAND '|' '^' '&' EQ NE '<' '>' LE GE LSHIFT RSHIFT '+' '-' '*' '/' '%' '('
+@g
+
+@*1 Grammar rules, an overview.
+The first natural step in transforming an existing parser into a
+`parser stack' for pretty printing is to understand the `anatomy' of
+the grammar. Not every grammar is suitable for such a transformation
+and in almost every case, some modifications are needed. The
+parser and lexer implementation for \ld\ is not terrible although it does
+have some idiosynchasies that could have been eliminated by a careful
+grammar redesign. Instead of invasive rewriting of significant
+portions of the grammar, the approach taken here merely omits some
+rules and partitions the grammar into several subsets, each of which
+is supposed to handle a well defined logical section of an \ld\ script
+file.
+
+One example of a trick used by the \ld\ parser that is not appropriate for a
+pretty printing grammar implements a way of handling the choice of the
+format of an input file. After a command line option that selects the
+input format has been read (or the format has been determined using
+some other method), the first token output by the lexer branches the
+parser to the appropriate portion of the full grammar.
+
+Since the token never appears as part of the input file there is no
+need to include this part of the main grammar for the purposes of
+typesetting.
+\traceparserstatestrue
+\tracestackstrue
+\tracerulestrue
+\traceactionstrue
+\tracelookaheadtrue
+\traceparseresultstrue
+\tracebadcharstrue
+\yyflexdebugtrue
+%\checktabletrue
+%
+\traceparserstatesfalse
+\tracestacksfalse
+\tracerulesfalse
+\traceactionsfalse
+\tracelookaheadfalse
+\traceparseresultsfalse
+\tracebadcharsfalse
+\yyflexdebugfalse
+\checktablefalse
+%
+\saveparseoutputfalse
+@<Ignored grammar rules@>=
+@G
+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
+;
+@g
+
+@ @<Grammar rules@>=
+@G
+@t}\vb{\inline\flatten}{@>
+filename:
+ NAME {@>@[TeX_( "/yy0{/noexpand/ldfilename{/the/yy(1)}}" );@]@=}
+;
+@g
+
+@ The simplest parser subset is intended to parse symbol definitions
+given in the command line that invokes the linker. Creating a parser
+for it involves almost no extra effort so we leave it in.
+
+Note that the simpliciy is somewhat deceptive as the syntax of
+\prodstyle{exp} is rather complex. That part of the grammar is needed
+elsewhere, however, so symbol definitions parsing costs almost nothing
+on top of the already required effort. The only practical use for this
+part of the \ld\ grammar is presenting examples in text.
+
+The\namedspot{pingpong} \TeX\ macro \.{\\ldlex@@defsym} switches the lexer state to
+\.{DEFSYMEXP} (see \locallink{stateswitchers}all the state switching
+macros\endlink\ in the chapter about the lexer implementation
+below). Switching lexer states from the parser presents some
+difficulties which can be overcome by careful design. For example, the
+state switching macros can be invoked before the lexer is called and
+initialized (when the parser performs a {\it default action\/}).
+@<Inline symbol definitions@>=
+@G
+defsym_expr:
+ {@>@[TeX_( "/ldlex@@defsym" );@]@=}
+ NAME '=' exp {@>@[TeX_( "/ldlex@@popstate" );@]@=}
+ ;
+@g
+
+@ {\it Syntax within an \MRI\ script file}\footnote{As explained at the
+beginning of this chapter, the text in {\it italics\/} was taken from
+the original comments by \ld\ parser and lexer programmers.}. The parser for typesetting
+is only intended to process \GNU\ \ld\ scripts and does not concern
+itself with any additional compatibility modes. For this reason, all
+support for \MRI\ style scripts has been omitted. One use for the
+section below is a small demonstration of the formatting tools that
+change the output of the \bison\ parser.
+@<\MRI\ style script rules@>=
+@G
+@t}\vb{\inline\flatten}{@>
+mri_script_file:
+ {@>@[TeX_( "/ldlex@@mri@@script" );@]@=}
+ mri_script_lines {@>@[TeX_( "/ldlex@@popstate" );@]@=}
+ ;
+
+mri_script_lines:
+ mri_script_lines mri_script_command NEWLINE
+ |
+ ;
+@t}\vb{\resetf}{@>
+mri_script_command:
+ CHIP exp
+ | CHIP exp ',' exp
+ | NAME {}
+ | LIST {}
+ | ORDER ordernamelist {}
+ | ENDWORD {}
+@t}\vb{\flatten}{@>
+ | PUBLIC NAME '=' exp {}
+ | PUBLIC NAME ',' exp {}
+ | PUBLIC NAME exp
+@t}\vb{\resetf}{@>
+ {}
+ | FORMAT NAME {}
+@t}\vb{\flatten}{@>
+ | SECT NAME ',' exp {}
+ | SECT NAME exp {}
+ | SECT NAME '=' exp
+@t}\vb{\resetf}{@>
+ {}
+@t}\vb{\flatten}{@>
+ | ALIGN_K NAME '=' exp {}
+ | ALIGN_K NAME ',' exp
+@t}\vb{\resetf}{@>
+ {}
+@t}\vb{\flatten}{@>
+ | ALIGNMOD NAME '=' exp {}
+ | ALIGNMOD NAME ',' exp {}
+@t}\vb{\resetf}{@>
+ {}
+ | ABSOLUTE mri_abs_name_list
+ | LOAD mri_load_name_list
+ | NAMEWORD NAME {}
+@t}\vb{\flatten}{@>
+ | ALIAS NAME ',' NAME {}
+ | ALIAS NAME ',' INT {}
+@t}\vb{\resetf}{@>
+ {}
+ | BASE exp {}
+ | TRUNCATE INT {}
+ | CASE casesymlist
+ | EXTERN extern_name_list
+@t}\vb{\flatten}{@>
+ | INCLUDE filename {@>@<Peek at a file@>@=}
+ mri_script_lines END
+@t}\vb{\resetf}{@>
+ {@>@<Close the file@>@=}
+ | START NAME {}
+ |
+ ;
+@t}\vb{\inline\flatten}{@>
+ordernamelist:
+ ordernamelist ',' NAME {}
+ | ordernamelist NAME {}
+ |
+ ;
+
+mri_load_name_list:
+ NAME {}
+ | mri_load_name_list ',' NAME {}
+ ;
+
+mri_abs_name_list:
+ NAME {}
+ | mri_abs_name_list ',' NAME {}
+ ;
+
+casesymlist:
+ {}
+ | NAME
+ | casesymlist ',' NAME
+ ;
+@g
+
+@ {\it Parsed as expressions so that commas separate entries.} The
+core of the parser consists of productions describing \GNU\ \ld\ linker
+scripts. The first rule is common to both \MRI\ and \GNU\ formats.
+@<\GNU\ \ld\ script rules@>=
+@G
+extern_name_list:
+ {@>@[TeX_( "/ldlex@@expression" );@]@=}
+ extern_name_list_body {@>@[TeX_( "/ldlex@@popstate" );@]@=}
+ ;
+
+extern_name_list_body:
+ NAME {}
+ | extern_name_list_body NAME {}
+ | extern_name_list_body ',' NAME {}
+ ;
+
+@ The top level productions simply define a script file as a list of
+script commands.
+@<\GNU\ \ld\ script rules@>=
+@G
+script_file:
+ {@>@[TeX_( "/ldlex@@both" );@]@=}
+ ifile_list {@>@[TeX_( "/getsecond{/yy(2)}/to/ldcmds/ldlex@@popstate" );@]@=}
+ ;
+
+ifile_list:
+ ifile_list ifile_p1 {@>@<Add the next command@>@=}
+ | {@>@[TeX_( "/yy0{{}{}}" );@]@=}
+ ;
+@g
+
+@ @<Add the next command@>=
+ @[TeX_( "/getfirst{/yy(1)}/to/toksa/getsecond{/yy(1)}/to/toksb" );@]@;
+ @[TeX_( "/getfirst{/yy(2)}/to/toksc/getsecond{/yy(2)}/to/toksd" );@]@;
+ @[TeXb( "/yytoksempty{/toksb}{/yy0{/the/yy(2)}}" );@]@;
+ @[TeXao( "{/yy0{{/the/toksc}{/the/toksb/noexpand/ldcommandseparator{/the/toksa}{/the/toksc}/the/toksd}}}" );@]@;
+
+@*1 Script internals.
+There are a number of different commands. For typesetting purposes,
+the handling of most of these can be significantly
+simplified. In the \prodstyle{GROUP} command there is no need to
+perform any actions upon entering the group, for
+instance. \prodstyle{INCLUDE} presents a special challenge. In
+the original grammar this command is followed by a general list of script
+commands (the contents of the included file) terminated by
+\prodstyle{END}. The `magic' of opening the file and inserting its
+contents into the stream being parsed is performed by the lexer and
+the parser in the
+background. The typesetting parser, on the other hand, only has to
+typeset the \prodstyle{INCLUDE} command itself and has no need for
+opening and parsing the file being included. We can simply change the
+grammar rule to omit the follow up script commands but that would
+require altering the existing grammar. \namedspot{pretendbuffersw}Since the command list
+(\prodstyle{ifile\_list}) is allowed to be empty,
+we simply \locallink{pretendbufferswlex}fake\endlink\ the
+inclusion of the file in the lexer by immediately outputting
+\prodstyle{END} upon entering the appropriate lexer state. One
+advantage in using this approach is the ability, when desired, to
+examine the included file for possible cross-referencing information.
+
+Each command is packaged with a qualifier that records its type for
+the rule that adds the fragment to the script file.
+@<\GNU\ \ld\ script rules@>=
+@G
+ifile_p1:
+ memory {@>@[TeX_( "/yy0{{mem}{/the/yy(1)}}" );@]@=}
+ | sections {@>@[TeX_( "/yy0{{sect}{/the/yy(1)}}" );@]@=}
+ | phdrs
+ | startup
+ | high_level_library
+ | low_level_library
+ | floating_point_support
+ | statement_anywhere {@>@[TeX_( "/yy0{{stmt}{/noexpand/ldstatement{/the/yy(1)}}}" );@]@=}
+ | version
+ | ';' {@>@[TeX_( "/yy0{{none}{}}" );@]@=}
+ | TARGET_K '(' NAME ')' {}
+ | SEARCH_DIR '(' filename ')' {}
+ | OUTPUT '(' filename ')' {}
+ | OUTPUT_FORMAT '(' NAME ')' {}
+ | OUTPUT_FORMAT '(' NAME ','
+ NAME ',' NAME ')' {}
+ | OUTPUT_ARCH '(' NAME ')' {}
+ | FORCE_COMMON_ALLOCATION {}
+ | INHIBIT_COMMON_ALLOCATION {}
+ | INPUT '(' input_list ')'
+ | GROUP {}
+ '(' input_list ')' {}
+ | MAP '(' filename ')' {}
+ | INCLUDE filename {@>@<Peek at a file@>@=}
+ ifile_list END {@>@<Add an \prodstyle{INCLUDE} statement@>@=}
+ | NOCROSSREFS '('
+ nocrossref_list ')' {}
+ | EXTERN '(' extern_name_list ')'
+ | INSERT_K AFTER NAME {}
+ | INSERT_K BEFORE NAME {}
+ | REGION_ALIAS '(' NAME ',' NAME ')' {}
+ | LD_FEATURE '(' NAME ')' {}
+ ;
+
+input_list:
+ NAME {}
+ | input_list ',' NAME {}
+ | input_list NAME {}
+ | LNAME {}
+ | input_list ',' LNAME {}
+ | input_list LNAME {}
+ | AS_NEEDED '(' {}
+ input_list ')' {}
+ | input_list ',' AS_NEEDED '(' {}
+ input_list ')' {}
+ | input_list AS_NEEDED '(' {}
+ input_list ')' {}
+ ;
+
+sections:
+ SECTIONS '{' sec_or_group_p1 '}' {@>@[TeX_( "/yy0{/noexpand/ldsections{/the/yy(3)}}" );@]@=}
+ ;
+
+sec_or_group_p1:
+ sec_or_group_p1 section {@>@<Add the next section@>@=}
+ | sec_or_group_p1 statement_anywhere {@>@<Add the next statement@>@=}
+ | {@>@[TeX_( "/yy0{}" );@]@=}
+ ;
+
+statement_anywhere:
+ ENTRY '(' NAME ')' {}
+ | assignment end {@>@<Carry on@>@=}
+ | ASSERT_K {@>@[TeX_( "/ldlex@@expression" );@]@=}
+ '(' exp ',' NAME ')' {@>@[TeX_( "/ldlex@@popstate" );@]@=}
+ ;
+@g
+
+@ @<Add the next section@>=
+ @[TeXb( "/yytoksempty{/yy(1)}{/yy0{/the/yy(2)}}" );@]@;
+ @[TeXao( "{/yy0{/the/yy(1)/noexpand/ldsectionseparator/the/yy(2)}}" );@]@;
+
+@ @<Add the next statement@>=
+ @[TeXb( "/yytoksempty{/yy(1)}{/yy0{/the/yy(2)}}" );@]@;
+ @[TeXao( "{/yy0{/the/yy(1)/noexpand/ldsectionseparator/ldstatement{/the/yy(2)}}}" );@]@;
+
+@ This is the default action performed by the parser when the parser
+writer does not supply one. For a minor gain in efficiency, this
+definition can be made empty.
+@<Carry on@>=
+ @[TeX_( "/yy0{/the/yy(1)}" );@]@;
+
+@ @<Peek at a file@>=
+ @[TeX_( "/ldlex@@script" );@]@;
+ @[TeX_( "/ldfile@@open@@command@@file{/yy(2)}" );@]@;
+
+@ @<Close the file@>=
+ @[TeX_( "/yy0{/noexpand/ldinclude{/the/yy(2)}}/ldlex@@popstate" );@]@;
+
+@ @<Add an \prodstyle{INCLUDE} statement@>=
+ @[TeX_( "/yy0{{inc}{/noexpand/ldinclude{/the/yy(2)}}}/ldlex@@popstate" );@]@;
+
+@ \tracebadcharstrue
+{\it The \prodstyle{'*'} and \prodstyle{'?'} cases are there because the lexer returns them as
+separate tokens rather than as \prodstyle{NAME}.}
+\tracebadcharsfalse
+@<Grammar rules@>=
+@G
+wildcard_name:
+ NAME {@>@<Carry on@>@=}
+ | '*' {@>@[TeX_( "/yy0{{*}{*}}" );@]@=}
+ | '?' {@>@[TeX_( "/yy0{{?}{?}}" );@]@=}
+ ;
+@g
+
+@ @<Grammar rules@>=
+@G
+wildcard_spec:
+ wildcard_name {}
+ | EXCLUDE_FILE '(' exclude_name_list ')' wildcard_name
+ {}
+ | SORT_BY_NAME '(' wildcard_name ')' {}
+ | SORT_BY_ALIGNMENT '(' wildcard_name ')'
+ {}
+ | SORT_NONE '(' wildcard_name ')'
+ {}
+ | SORT_BY_NAME '(' SORT_BY_ALIGNMENT '(' wildcard_name ')' ')'
+ {}
+ | SORT_BY_NAME '(' SORT_BY_NAME '(' wildcard_name ')' ')'
+ {}
+ | SORT_BY_ALIGNMENT '(' SORT_BY_NAME '(' wildcard_name ')' ')'
+ {}
+ | SORT_BY_ALIGNMENT
+@t}\vb{\breakline}{@>
+ '(' SORT_BY_ALIGNMENT '(' wildcard_name ')' ')'
+ {}
+ | SORT_BY_NAME
+@t}\vb{\breakline}{@>
+ '(' EXCLUDE_FILE '(' exclude_name_list ')' wildcard_name ')'
+ {}
+ | SORT_BY_INIT_PRIORITY '(' wildcard_name ')'
+ {}
+ ;
+
+sect_flag_list:
+ NAME {}
+ | sect_flag_list '&' NAME {}
+ ;
+
+sect_flags:
+ INPUT_SECTION_FLAGS '(' sect_flag_list ')' {}
+ ;
+
+exclude_name_list:
+ exclude_name_list wildcard_name {}
+ | wildcard_name {}
+ ;
+
+file_NAME_list:
+ file_NAME_list opt_comma wildcard_spec {@>@[TeX_( "/yy0{/the/yy(1)/noexpand/ldspace/noexpand/ldregexp{/the/yy(2)}}" );@]@=}
+ | wildcard_spec {@>@[TeX_( "/yy0{/noexpand/ldregexp{/the/yy(1)}}" );@]@=}
+ ;
+
+input_section_spec_no_keep:
+ NAME {}
+ | sect_flags NAME {}
+ | '[' file_NAME_list ']' {}
+ | sect_flags '[' file_NAME_list ']' {}
+ | wildcard_spec '(' file_NAME_list ')' {@>@[TeX_( "/yy0{/noexpand/ldregexp{/the/yy(1)}(/the/yy(3))}" );@]@=}
+ | sect_flags wildcard_spec '(' file_NAME_list ')'
+ {}
+ ;
+@g
+
+@ @<Grammar rules@>=
+@G
+input_section_spec:
+ input_section_spec_no_keep {@>@<Carry on@>@=}
+ | KEEP '(' {}
+ input_section_spec_no_keep ')' {@>@[TeX_( "/yy0{/mathop{/hbox{/noexpand/ttl keep}(/the/yy(4))}}" );@]@=}
+ ;
+
+statement:
+ assignment end
+ | CREATE_OBJECT_SYMBOLS {}
+ | ';' {@>@[TeX_( "/yy0{}" );@]@=}
+ | CONSTRUCTORS {}
+ | SORT_BY_NAME '(' CONSTRUCTORS ')' {}
+ | input_section_spec
+ | length '(' mustbe_exp ')' {}
+ | FILL '(' fill_exp ')' {}
+ | ASSERT_K {@>@[TeX_( "/ldlex@@expression" );@]@=}
+ '(' exp ',' NAME ')' end {@>@[TeX_( "/ldlex@@popstate" );@]@=}
+ | INCLUDE filename {@>@<Peek at a file@>@=}
+ statement_list_opt END {@>@<Close the file@>@=}
+ ;
+
+statement_list:
+ statement_list statement {@>@<Attach a statement to a statement list@>@=}
+ | statement {@>@<Start a statement list with a statement@>@=}
+ ;
+
+statement_list_opt:
+ {@>@[TeX_( "/yy0{}" );@]@=}
+ | statement_list {@>@<Carry on@>@=}
+ ;
+@g
+
+@ @<Attach a statement to a statement list@>=
+ @[TeX_( "/yy0{/the/yy(1)/yytoksempty{/yy(2)}{}{/yytoksempty{/yy(1)}{}{/noexpand/ldor}{/the/yy(2)}}}" );@]
+
+@ @<Start a statement list with a statement@>=
+ @[TeX_( "/yy0{/yytoksempty{/yy(1)}{}{{/the/yy(1)}}}" );@]
+
+@ @<Grammar rules@>=
+@G
+@t}\vb{\inline\flatten}{@>
+length:
+ QUAD {}
+ | SQUAD {}
+ | LONG {}
+ | SHORT {}
+ | BYTE {}
+ ;
+
+fill_exp:
+ mustbe_exp {@>@<Carry on@>@=}
+ ;
+
+fill_opt:
+ '=' fill_exp {@>@[TeX_( "/yy0{/noexpand/ldfill{/the/yy(2)}}" );@]@=}
+ | {@>@[TeX_( "/yy0{}" );@]@=}
+ ;
+
+@t}\vb{\resetf}{@>
+assign_op:
+ PLUSEQ {@>@[TeX_( "/yy(0)={/MRL{+{/K}}}" );@]@=}
+ | MINUSEQ {@>@[TeX_( "/yy(0)={/MRL{-{/K}}}" );@]@=}
+@t}\vb{\inline\flatten}{@>
+ | MULTEQ {@>@[TeX_( "/yy(0)={/MRL*{/K}}" );@]@=}
+ | DIVEQ {@>@[TeX_( "/yy(0)={/MRL{{/div}{/K}}}" );@]@=}
+ | LSHIFTEQ {@>@[TeX_( "/yy(0)={/MRL{{/ll}{/K}}}" );@]@=}
+ | RSHIFTEQ {@>@[TeX_( "/yy(0)={/MRL{{/gg}{/K}}}" );@]@=}
+ | ANDEQ {@>@[TeX_( "/yy(0)={/Xandxeq}" );@]@=}
+ | OREQ {@>@[TeX_( "/yy(0)={/Xorxeq}" );@]@=}
+ ;
+
+end: ';' | ','
+ ;
+
+opt_comma: ',' |
+ ;
+@t}\vb{\resetf}{@>
+@g
+
+@ Assignments are not expressions as in \Cee.
+@<Grammar rules@>=
+@G
+assignment:
+ NAME '=' mustbe_exp {@>@<Process simple assignment@>@=}
+ | NAME assign_op mustbe_exp {@>@<Process compound assignment@>@=}
+ | HIDDEN '(' NAME '=' mustbe_exp ')' {}
+ | PROVIDE '(' NAME '=' mustbe_exp ')' {}
+ | PROVIDE_HIDDEN '(' NAME '=' mustbe_exp ')' {}
+ ;
+@g
+
+@ @<Process simple assignment@>=
+ @[TeX_( "/yy0{/noexpand/ldassignment{/noexpand/ldregexp{/the/yy(1)}}{/K}{/the/yy(3)}}" );@]
+
+@ @<Process compound assignment@>=
+ @[TeX_( "/yy0{/noexpand/ldassignment{/noexpand/ldregexp{/the/yy(1)}}{/the/yy(2)}{/the/yy(3)}}" );@]
+
+@ @<Grammar rules@>=
+@G
+memory:
+ MEMORY '{' memory_spec_list_opt '}' {@>@[TeX_( "/yy0{/noexpand/ldmemory{/the/yy(3)}}" );@]@=}
+ ;
+
+memory_spec_list_opt:
+ memory_spec_list {@>@<Carry on@>@=}
+ | {@>@[TeX_( "/yy0{}" );@]@=}
+ ;
+
+memory_spec_list:
+ memory_spec_list opt_comma memory_spec {@>@[TeX_( "/yy0{/the/yy(1)/the/yy(3)}" );@]@=}
+ | memory_spec {@>@[TeX_( "/yy0{/the/yy(1)}" );@]@=}
+ ;
+
+
+memory_spec:
+ NAME {}
+ attributes_opt ':'
+ origin_spec
+@t}\vb{\breakline}{@>
+ opt_comma length_spec {@>@[TeX_( "/yy0{/noexpand/ldmemoryspec{/the/yy(1)}{/the/yy(3)}{/the/yy(5)}{/the/yy(7)}}" );@]@=}
+ | INCLUDE filename {@>@<Peek at a file@>@=}
+ memory_spec_list_opt END {@>@<Close the file@>@=}
+ ;
+@g
+
+@ @<Grammar rules@>=
+@G
+origin_spec:
+ ORIGIN '=' mustbe_exp {@>@[TeX_( "/yy0{/noexpand/ldoriginspec{/the/yy(3)}}" );@]@=}
+ ;
+
+length_spec:
+ LENGTH '=' mustbe_exp {@>@[TeX_( "/yy0{/noexpand/ldlengthspec{/the/yy(3)}}" );@]@=}
+ ;
+
+attributes_opt:
+
+ {@>@[TeX_( "/yy0{}" );@]@=}
+ | '(' attributes_list ')' {@>@[TeX_( "/yy0{/the/yy(2)}" );@]@=}
+ ;
+
+attributes_list:
+ attributes_string {@>@[TeX_( "/yy0{/the/yy(1)}" );@]@=}
+ | attributes_list attributes_string {@>@[TeX_( "/yy0{/the/yy(1)/noexpand/ldspace/the/yy(2)}" );@]@=}
+ ;
+
+attributes_string:
+ NAME {@>@[TeX_( "/yy0{/noexpand/ldattributes{/the/yy(1)}}" );@]@=}
+ | '!' NAME {@>@[TeX_( "/yy0{/noexpand/ldattributesneg{/the/yy(2)}}" );@]@=}
+ ;
+
+startup:
+ STARTUP '(' filename ')' {}
+ ;
+
+high_level_library:
+ HLL '(' high_level_library_NAME_list ')'
+ | HLL '(' ')' {}
+ ;
+
+high_level_library_NAME_list:
+ high_level_library_NAME_list opt_comma filename
+ {}
+ | filename {}
+ ;
+
+low_level_library:
+ SYSLIB '(' low_level_library_NAME_list ')' {}
+ ;
+
+low_level_library_NAME_list:
+ low_level_library_NAME_list opt_comma filename
+ {}
+ | {}
+ ;
+
+floating_point_support:
+ FLOAT {}
+ | NOFLOAT {}
+ ;
+
+nocrossref_list:
+ {}
+ | NAME nocrossref_list {}
+ | NAME ',' nocrossref_list {}
+ ;
+
+mustbe_exp:
+ {@>@[TeX_( "/ldlex@@expression" );@]@=}
+ exp {@>@[TeX_( "/ldlex@@popstate/yy0{/the/yy(2)}" );@]@=}
+ ;
+@g
+
+@*1 {\ifheader\ninepoint\fi\prodstyle{SECTIONS}} and expressions.
+The linker supports an extensive range of expressions. The precedence
+mechanism provided by \bison\ is used to present the composition of
+expressions out of simpler chunks and basic building blocks tied
+together by algebraic operations.
+@<Grammar rules@>=
+@G
+exp :
+ '-' exp %prec UNARY {@>@[TeX_( "/yy0{{-/the/yy(2)}}" );@]@=}
+ | '(' exp ')' {@>@[TeX_( "/yy0{(/the/yy(2))}" );@]@=}
+ | NEXT '(' exp ')' %prec UNARY {@>@[TeX_( "/yy0{/hbox{/nx/ssf next}(/the/yy(3))}" );@]@=}
+ | '!' exp %prec UNARY {@>@[TeX_( "/yy0{{/noexpand/CM/the/yy(2)}}" );@]@=}
+ | '+' exp %prec UNARY {@>@[TeX_( "/yy0{{+/the/yy(2)}}" );@]@=}
+ | '~' exp %prec UNARY {@>@[TeX_( "/yy0{{/noexpand/R/the/yy(2)}}" );@]@=}
+ | exp '*' exp {@>@[TeX_( "/yy0{/the/yy(1)/noexpand/times/the/yy(3)}" );@]@=}
+ | exp '/' exp {@>@[TeX_( "/yy0{/the/yy(1)/noexpand///the/yy(3)}" );@]@=}
+ | exp '%' exp {@>@[TeX_( "/yy0{/the/yy(1)/noexpand/div/the/yy(3)}" );@]@=}
+ | exp '+' exp {@>@[TeX_( "/yy0{/the/yy(1)+/the/yy(3)}" );@]@=}
+ | exp '-' exp {@>@[TeX_( "/yy0{/the/yy(1)-/the/yy(3)}" );@]@=}
+ | exp LSHIFT exp {@>@[TeX_( "/yy0{/the/yy(1)/noexpand/ll/the/yy(3)}" );@]@=}
+ | exp RSHIFT exp {@>@[TeX_( "/yy0{/the/yy(1)/noexpand/gg/the/yy(3)}" );@]@=}
+ | exp EQ exp {@>@[TeX_( "/yy0{/the/yy(1)=/the/yy(3)}" );@]@=}
+ | exp NE exp {@>@[TeX_( "/yy0{/the/yy(1)/noexpand/not=/the/yy(3)}" );@]@=}
+ | exp LE exp {@>@[TeX_( "/yy0{/the/yy(1)/noexpand/leq/the/yy(3)}" );@]@=}
+ | exp GE exp {@>@[TeX_( "/yy0{/the/yy(1)/noexpand/geq/the/yy(3)}" );@]@=}
+ | exp '<' exp {@>@[TeX_( "/yy0{/the/yy(1)</the/yy(3)}" );@]@=}
+ | exp '>' exp {@>@[TeX_( "/yy0{/the/yy(1)>/the/yy(3)}" );@]@=}
+ | exp '&' exp {@>@[TeX_( "/yy0{/the/yy(1)/noexpand/AND/the/yy(3)}" );@]@=}
+ | exp '^' exp {@>@[TeX_( "/yy0{/the/yy(1)/noexpand/XOR/the/yy(3)}" );@]@=}
+ | exp '|' exp {@>@[TeX_( "/yy0{/the/yy(1)/noexpand/OR/the/yy(3)}" );@]@=}
+ | exp '?' exp ':' exp {@>@<Process a primitive conditional@>@=}
+ | exp ANDAND exp {@>@[TeX_( "/yy0{/the/yy(1)/noexpand/V/the/yy(3)}" );@]@=}
+ | exp OROR exp {@>@[TeX_( "/yy0{/the/yy(1)/noexpand/W/the/yy(3)}" );@]@=}
+@g
+
+@ More atomic expression types specific to the linker's function.
+@<Grammar rules@>=
+@G
+exp :
+ DEFINED '(' NAME ')' {}
+ | INT {}
+ | SIZEOF_HEADERS {}
+ | ALIGNOF '(' NAME ')' {}
+ | SIZEOF '(' NAME ')' {}
+ | ADDR '(' NAME ')' {}
+ | LOADADDR '(' NAME ')' {}
+ | CONSTANT '(' NAME ')' {}
+ | ABSOLUTE '(' exp ')' {}
+ | ALIGN_K '(' exp ')' {@>@[TeX_( "/yy0{/nx/mathop{/hbox{/nx/ssf align}}(/the/yy(3))}" );@]@=}
+ | ALIGN_K '(' exp ',' exp ')' {}
+ | DATA_SEGMENT_ALIGN '(' exp ',' exp ')' {}
+ | DATA_SEGMENT_RELRO_END '(' exp ',' exp ')' {}
+ | DATA_SEGMENT_END '(' exp ')' {}
+ | SEGMENT_START '(' NAME ',' exp ')' {}
+ | BLOCK '(' exp ')' {}
+ | NAME {@>@[TeX_( "/yy0{/noexpand/ldregexp{/the/yy(1)}}" );@]@=}
+ | MAX_K '(' exp ',' exp ')' {}
+ | MIN_K '(' exp ',' exp ')' {}
+ | ASSERT_K '(' exp ',' NAME ')' {}
+ | ORIGIN '(' NAME ')' {}
+ | LENGTH '(' NAME ')' {}
+ | LOG2CEIL '(' exp ')' {}
+ ;
+@g
+
+@ @<Process a primitive conditional@>=
+@q TeX_( "/yy0{/hbox{/nx/ttl let }/nx/xi(0)=/the/yy(5): /nx/xi(/nx/CM0)=/the/yy(3)/hbox{ /nx/ttl do }/xi(/the/yy(1))}" );@>
+@[TeX_( "/yy0{/hbox{/nx/ttl do }/xi(/the/yy(1))/hbox{ /nx/ttl where }" );@>
+@[TeX_( " {/let/nx/{/nx/bigbracedel/nx/xi(x)=/nx/cases{/the/yy(5)& if /inmath{x=0}/cr/the/yy(3)& if /inmath{x/nx/not=0}}}}" );@]
+
+@ @<Grammar rules@>=
+@G
+memspec_at_opt:
+ AT '>' NAME {@>@[TeX_( "/yy0{/the/yy(3)}" );@]@=}
+ | {@>@[TeX_( "/yy0{}" );@]@=}
+ ;
+
+opt_at:
+ AT '(' exp ')' {@>@[TeX_( "/yy0{/the/yy(3)}" );@]@=}
+ | {@>@[TeX_( "/yy0{}" );@]@=}
+ ;
+
+opt_align:
+ ALIGN_K '(' exp ')' {@>@[TeX_( "/yy0{/the/yy(3)}" );@]@=}
+ | {@>@[TeX_( "/yy0{}" );@]@=}
+ ;
+
+opt_align_with_input:
+ ALIGN_WITH_INPUT {@>@[TeX_( "/yy0{align with input}" );@]@=}
+ | {@>@[TeX_( "/yy0{}" );@]@=}
+ ;
+
+opt_subalign:
+ SUBALIGN '(' exp ')' {@>@[TeX_( "/yy0{/the/yy(3)}" );@]@=}
+ | {@>@[TeX_( "/yy0{}" );@]@=}
+ ;
+
+sect_constraint:
+ ONLY_IF_RO {@>@[TeX_( "/yy0{only/_if/_ro}" );@]@=}
+ | ONLY_IF_RW {@>@[TeX_( "/yy0{only/_if/_rw}" );@]@=}
+ | SPECIAL {@>@[TeX_( "/yy0{special}" );@]@=}
+ | {@>@[TeX_( "/yy0{}" );@]@=}
+ ;
+
+@g
+
+@ {\it The \prodstyle{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 \prodstyle{GROUP} is supposed to mean.} A careful
+analysis of the productions below reveals some
+pitfalls in the parser/lexer interaction setup that uses the state switching
+macros (or functions in the case of the original parser). The switch
+to the \.{EXPRESSION} state at the end of the production for
+\prodstyle{section} is invoked before \prodstyle{opt\_comma} which can
+be empty. This means that the next (lookahead) token (which could be a
+\prodstyle{NAME} in a different context) might be read before the
+lexer is in the appropriate state. In practice, the names of the sections
+and other \prodstyle{NAME}s are usually pretty straightforward so this
+parser idiosynchrasy is unlikely to lead to a genuine problem. Since
+the goal was to keep the original grammar intact as much as possible,
+it was decided to leave this production unchanged.
+@<Grammar rules@>=
+@G
+section:
+ NAME {@>@[TeX_( "/ldlex@@expression" );@]@=}
+ opt_exp_with_type opt_at opt_align opt_align_with_input
+@t}\vb{\breakline}{@>
+ opt_subalign {@>@[TeX_( "/ldlex@@popstate/ldlex@@script" );@]@=}
+ sect_constraint
+ '{' {}
+ statement_list_opt
+ '}' {@>@[TeX_( "/ldlex@@popstate/ldlex@@expression" );@]@=}
+ memspec_opt memspec_at_opt phdr_opt fill_opt
+ {@>@[TeX_( "/ldlex@@popstate" );@]@=}
+ opt_comma {@>@<Record a named section@>@=}
+ | OVERLAY {@>@[TeX_( "/ldlex@@expression" );@]@=}
+ opt_exp_without_type opt_nocrossrefs opt_at opt_subalign
+ {@>@[TeX_( "/ldlex@@popstate/ldlex@@script" );@]@=}
+ '{' {}
+ overlay_section '}' {@>@[TeX_( "/ldlex@@popstate/ldlex@@expression" );@]@=}
+ memspec_opt memspec_at_opt phdr_opt fill_opt
+ {@>@[TeX_( "/ldlex@@popstate" );@]@=}
+ opt_comma {@>@<Record an overlay section@>@=}
+ | GROUP {@>@[TeX_( "/ldlex@@expression" );@]@=}
+ opt_exp_with_type {@>@[TeX_( "/ldlex@@popstate" );@]@=}
+ '{' sec_or_group_p1 '}'
+ | INCLUDE filename {@>@<Peek at a file@>@=}
+ sec_or_group_p1 END
+ {@>@<Close the file@>@=}
+ ;
+@g
+
+@ @<Record a named section@>=
+ @[TeXb( "/yy0{/nx/ldnamedsection{/the/yy(1)}{/the/yy(3)}{/the/yy(4)}" );@]@;
+ @[TeXf( " {{/the/yy(5)}{/the/yy(6)}{/the/yy(7)}}" );@]@;/* alignment */
+ @[TeXf( " {/the/yy(9)}{/the/yy(12)}" );@]@;
+ @[TeXfo( " {{/the/yy(15)}{/the/yy(16)}{/the/yy(17)}{/the/yy(18)}}}" );@]@; /*memory specifiers */
+
+@ @<Record an overlay section@>=
+
+@ @<Grammar rules@>=
+@G
+type:
+ NOLOAD {@>@[TeX_( "/yy0{noload}" );@]@=}
+ | DSECT {@>@[TeX_( "/yy0{dsect}" );@]@=}
+ | COPY {@>@[TeX_( "/yy0{copy}" );@]@=}
+ | INFO {@>@[TeX_( "/yy0{info}" );@]@=}
+ | OVERLAY {@>@[TeX_( "/yy0{overlay}" );@]@=}
+ ;
+
+atype:
+ '(' type ')' {@>@[TeX_( "/yy0{/noexpand/ldtype{/the/yy(2)}}" );@]@=}
+ | '(' ')' {@>@[TeX_( "/yy0{/noexpand/ldtype{}}" );@]@=}
+ | {@>@[TeX_( "/yy0{}" );@]@=}
+ ;
+@g
+
+@ {\it The \prodstyle{BIND} cases are to support the \gcc\ |svr3.ifile|
+script. They aren't intended to implement full support for the
+\prodstyle{BIND} keyword. I'm not even sure what \prodstyle{BIND}
+is supposed to mean.}
+@<Grammar rules@>=
+@G
+opt_exp_with_type:
+ exp atype ':' {@>@[TeX_( "/yy0{{}{/the/yy(1)}{}{}{/the/yy(2)}}" );@]@=}
+ | atype ':' {@>@[TeX_( "/yy0{{}{}{}{}{/the/yy(1)}}" );@]@=}
+ | BIND '(' exp ')' atype ':' {@>@[TeX_( "/yy0{{bind}{/the/yy(3)}{}{}{/the/yy(5)}}" );@]@=}
+ | BIND '(' exp ')' BLOCK '(' exp ')' atype ':'
+ {@>@[TeX_( "/yy0{{bind}{/the/yy(3)}{block}{/the/yy(7)}{/the/yy(9)}}" );@]@=}
+ ;
+
+opt_exp_without_type:
+ exp ':' {}
+ | ':' {}
+ ;
+
+opt_nocrossrefs:
+ {}
+ | NOCROSSREFS {}
+ ;
+
+memspec_opt:
+ '>' NAME {@>@[TeX_( "/yy0{/the/yy(2)}" );@]@=}
+ | {@>@[TeX_( "/yy0{}" );@]@=}
+ ;
+
+phdr_opt:
+ {@>@[TeX_( "/yy0{}" );@]@=}
+ | phdr_opt ':' NAME {@>@<Add another pheader@>@=}
+ ;
+
+overlay_section:
+
+ | overlay_section
+ NAME {@>@[TeX_( "/ldlex@@script" );@]@=}
+ '{' statement_list_opt '}' {@>@[TeX_( "/ldlex@@popstate/ldlex@@expression" );@]@=}
+ phdr_opt fill_opt {@>@[TeX_( "/ldlex@@popstate" );@]@=}
+ opt_comma
+ ;
+@g
+
+@ @<Add another pheader@>=
+ @[TeXb( "/yytoksempty{/yy(1)}{/yy0{{/the/yy(3)}}}" );@]@;
+ @[TeXao( "{/yy0{/the/yy(1)/noexpand/ldor{/the/yy(3)}}}" );@]@;
+
+@ @<Grammar rules@>=
+@G
+phdrs:
+ PHDRS '{' phdr_list '}'
+ ;
+
+phdr_list:
+
+ | phdr_list phdr
+ ;
+
+phdr:
+ NAME {@>@[TeX_( "/ldlex@@expression" );@]@=}
+ phdr_type phdr_qualifiers {@>@[TeX_( "/ldlex@@popstate" );@]@=}
+ ';' {}
+ ;
+
+phdr_type:
+ exp {}
+ ;
+
+phdr_qualifiers:
+ {}
+ | NAME phdr_val phdr_qualifiers {}
+ | AT '(' exp ')' phdr_qualifiers {}
+ ;
+
+phdr_val:
+ {}
+ | '(' exp ')' {}
+ ;
+@g
+
+@*1 Other types of script files. At present time other script types
+are ignored, although some of the rules are used in linker scripts
+that are processed by the parser.
+@<Dynamic list file rules@>=
+@G
+dynamic_list_file:
+ {@>@[TeX_( "/ldlex@@version@@file" );@]@=}
+ dynamic_list_nodes {@>@[TeX_( "/ldlex@@popstate" );@]@=}
+ ;
+
+dynamic_list_nodes:
+ dynamic_list_node
+ | dynamic_list_nodes dynamic_list_node
+ ;
+
+dynamic_list_node:
+ '{' dynamic_list_tag '}' ';'
+ ;
+
+dynamic_list_tag:
+ vers_defns ';' {}
+ ;
+@g
+
+@ {\it This syntax is used within an external version script file.}
+@<Version file rules@>=
+@G
+version_script_file:
+ {@>@[TeX_( "/ldlex@@version@@file" );@]@=}
+ vers_nodes {@>@[TeX_( "/ldlex@@popstate" );@]@=}
+ ;
+@g
+
+@ {\it This is used within a normal linker script file.}
+@<Grammar rules@>=
+@G
+version:
+ {@>@[TeX_( "/ldlex@@version@@script" );@]@=}
+ VERSIONK '{' vers_nodes '}' {@>@[TeX_( "/ldlex@@popstate" );@]@=}
+ ;
+
+vers_nodes:
+ vers_node
+ | vers_nodes vers_node
+ ;
+
+vers_node:
+ '{' vers_tag '}' ';' {}
+ | VERS_TAG '{' vers_tag '}' ';' {}
+ | VERS_TAG '{' vers_tag '}' verdep ';' {}
+ ;
+
+verdep:
+ VERS_TAG {}
+ | verdep VERS_TAG {}
+ ;
+
+vers_tag:
+ {}
+ | vers_defns ';' {}
+ | GLOBAL ':' vers_defns ';' {}
+ | LOCAL ':' vers_defns ';' {}
+ | GLOBAL ':' vers_defns ';' LOCAL ':' vers_defns ';'
+ {}
+ ;
+
+vers_defns:
+ VERS_IDENTIFIER {}
+ | NAME {}
+ | vers_defns ';' VERS_IDENTIFIER {}
+ | vers_defns ';' NAME {}
+ | vers_defns ';' EXTERN NAME '{' {}
+ vers_defns opt_semicolon '}' {}
+ | EXTERN NAME '{' {}
+ vers_defns opt_semicolon '}' {}
+ | GLOBAL {}
+ | vers_defns ';' GLOBAL {}
+ | LOCAL {}
+ | vers_defns ';' LOCAL {}
+ | EXTERN {}
+ | vers_defns ';' EXTERN {}
+ ;
+@t}\vb{\inline\flatten}{@>
+opt_semicolon:
+
+ | ';'
+ ;
+@g