1 %{
2 /* Parser for linker scripts
3 Copyright (C) 2001, 2002, 2003, 2004, 2005
4 Craig Franklin
5
6 This file is part of gputils.
7
8 gputils is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
11 any later version.
12
13 gputils is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with gputils; see the file COPYING. If not, write to
20 the Free Software Foundation, 59 Temple Place - Suite 330,
21 Boston, MA 02111-1307, USA. */
22
23 #include "stdhdr.h"
24
25 #include "libgputils.h"
26 #include "gplink.h"
27 #include "scan.h"
28 #include "script.h"
29
yyerror(const char * Message)30 void yyerror(const char *Message)
31 {
32 script_error(Message, NULL);
33 }
34
35 int yylex(void);
36
37 /************************************************************************/
38
39 /* Some simple functions for building parse trees */
40
41 static pnode_t *
_mk_pnode(enum pnode_tag Tag)42 _mk_pnode(enum pnode_tag Tag)
43 {
44 pnode_t *new = GP_Malloc(sizeof(*new));
45
46 new->tag = Tag;
47 return new;
48 }
49
50 static pnode_t *
_mk_constant(long Value)51 _mk_constant(long Value)
52 {
53 pnode_t *new = _mk_pnode(PTAG_CONSTANT);
54
55 PnConstant(new) = Value;
56 return new;
57 }
58
59 static pnode_t *
_mk_symbol(const char * String)60 _mk_symbol(const char *String)
61 {
62 pnode_t *new = _mk_pnode(PTAG_SYMBOL);
63
64 PnSymbol(new) = String;
65 return new;
66 }
67
68 /*
69 static pnode_t *
70 _mk_string(const char *String)
71 {
72 pnode_t *new = _mk_pnode(PTAG_STRING);
73
74 PnString(new) = String;
75 return new;
76 }
77
78 */
79
80 static pnode_t *
_mk_list(pnode_t * Head,pnode_t * Tail)81 _mk_list(pnode_t *Head, pnode_t *Tail)
82 {
83 pnode_t *new = _mk_pnode(PTAG_LIST);
84
85 PnListHead(new) = Head;
86 PnListTail(new) = Tail;
87 return new;
88 }
89
90 static pnode_t *
_mk_2op(int Op,pnode_t * Pnode0,pnode_t * Pnode1)91 _mk_2op(int Op, pnode_t *Pnode0, pnode_t *Pnode1)
92 {
93 pnode_t *new = _mk_pnode(PTAG_BINOP);
94
95 PnBinOpOp(new) = Op;
96 PnBinOpP0(new) = Pnode0;
97 PnBinOpP1(new) = Pnode1;
98 return new;
99 }
100
101 /*
102 static pnode_t *
103 _mk_1op(int Op, pnode_t *Pnode)
104 {
105 pnode_t *new = _mk_pnode(PTAG_UNOP);
106
107 PnUnOpOp(new) = Op;
108 PnUnOpP0(new) = Pnode;
109 return new;
110 }
111
112 */
113
114 %}
115
116 /* Bison declarations */
117
118 %union {
119 int i;
120 long l;
121 char *s;
122 struct pnode *p;
123 }
124
125 %token <s> SYMBOL
126 %token <s> LIBPATH
127 %token <s> LKRPATH
128 %token <s> STRING
129 %token <s> LEXEOF 0 "end of file"
130 %token <s> ERROR
131 %token <l> NUMBER
132 %token DEFINE
133 %token IFDEF
134 %token ELSE
135 %token FI
136 %type <i> '='
137 %type <i> '+'
138 %type <i> '-'
139 %type <i> '/'
140 %type <i> '*'
141 %type <i> e1op
142 %type <l> macroval
143 %type <i> aop
144
145 %type <p> e0
146 %type <p> e1
147 %type <p> parameter_list
148 %type <p> path_list
149
150 %%
151 /* Grammar rules */
152
153 program:
154 line
155 | error
156 | program '\n' {
157 ++state.src->line_number;
158 } line
159 ;
160
161 line:
162 /* empty */
163 |
164 LIBPATH path_list
165 {
166 if ((state.ifdef == NULL) || (state.ifdef->is_true)) {
167 script_add_path($2);
168 }
169 }
170 |
171 LKRPATH path_list
172 {
173 if ((state.ifdef == NULL) || (state.ifdef->is_true)) {
174 script_add_path($2);
175 }
176 }
177 |
178 SYMBOL parameter_list
179 {
180 if ((state.ifdef == NULL) || (state.ifdef->is_true)) {
181 script_execute_command($1, $2);
182 }
183 }
184 |
185 STRING parameter_list
186 {
187 if ((state.ifdef == NULL) || (state.ifdef->is_true)) {
188 script_execute_command($1, $2);
189 }
190 }
191 |
192 ERROR
193 {
194 if ((state.ifdef == NULL) || (state.ifdef->is_true)) {
195 yyerror($1);
196 }
197 }
198 |
199 DEFINE SYMBOL macroval aop macroval
200 {
201 /* Contrary to documentation, the mplink 4.38 does not seem
202 to care if the macro has already been defined or if the
203 parameters to the operation are undefined. */
204 if ((state.ifdef == NULL) || (state.ifdef->is_true)) {
205 long newval;
206 long lh;
207 long rh;
208
209 newval = 0;
210 lh = $3;
211 rh = $5;
212 switch ($4) {
213 case '+': newval = lh + rh; break;
214 case '-': newval = lh - rh; break;
215 case '*': newval = lh * rh; break;
216 case '/': {
217 if (rh == 0) {
218 yyerror("Division by zero.");
219 }
220 else {
221 newval = lh / rh;
222 }
223 break;
224 }
225 }
226 script_add_symbol_value($2, newval);
227 }
228 }
229 |
230 IFDEF SYMBOL
231 {
232 ifdef_t *ifdef = GP_Malloc(sizeof(*ifdef));
233
234 ifdef->is_true = (((state.ifdef == NULL) || state.ifdef->is_true) &&
235 gp_sym_get_symbol(state.script_symbols, $2));
236 ifdef->in_else = false;
237 ifdef->prev = state.ifdef;
238 state.ifdef = ifdef;
239 }
240 |
241 ELSE
242 {
243 if ((state.ifdef == NULL) || (state.ifdef->in_else)) {
244 yyerror("#ELSE without #IFDEF in linker script.");
245 }
246 else {
247 state.ifdef->is_true = ((!state.ifdef->is_true) &&
248 (state.ifdef->prev == NULL || state.ifdef->prev->is_true));
249 state.ifdef->in_else = true;
250 }
251 }
252 |
253 FI
254 {
255 if (state.ifdef == NULL)
256 yyerror("#FI without #IFDEF in linker script.");
257 else {
258 ifdef_t *ifdef = state.ifdef;
259
260 state.ifdef = state.ifdef->prev;
261 free(ifdef);
262 }
263 }
264 ;
265
266 path_list:
267 SYMBOL
268 {
269 $$ = _mk_list(_mk_symbol($1), NULL);
270 }
271 |
272 SYMBOL ';' path_list
273 {
274 $$ = _mk_list(_mk_symbol($1), $3);
275 }
276 |
277 STRING
278 {
279 $$ = _mk_list(_mk_symbol($1), NULL);
280 }
281 |
282 STRING ';' path_list
283 {
284 $$ = _mk_list(_mk_symbol($1), $3);
285 }
286 ;
287
288 parameter_list:
289 e1
290 {
291 $$ = _mk_list($1, NULL);
292 }
293 |
294 e1 parameter_list
295 {
296 $$ = _mk_list($1, $2);
297 }
298 ;
299
300 e1:
301 e0
302 |
303 e1 e1op e0
304 {
305 $$ = _mk_2op($2, $1, $3);
306 }
307 ;
308
309 e1op: '=' ;
310
311 e0:
312 SYMBOL
313 {
314 $$ = _mk_symbol($1);
315 }
316 |
317 STRING
318 {
319 $$ = _mk_symbol($1);
320 }
321 |
322 NUMBER
323 {
324 $$ = _mk_constant($1);
325 }
326 ;
327
328 macroval:
329 SYMBOL
330 {
331 $$ = script_get_symbol_value($1);
332 }
333 |
334 NUMBER
335 ;
336
337 aop: '+' | '-' | '/' | '*' ;
338
339 %%
340