]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - ld/ldexp.c
PR ld/12356
[thirdparty/binutils-gdb.git] / ld / ldexp.c
CommitLineData
252b5132 1/* This module handles expression trees.
a2b64bed 2 Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
ea7c2e6c 3 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
87f2a346 4 Free Software Foundation, Inc.
8c95a62e 5 Written by Steve Chamberlain of Cygnus Support <sac@cygnus.com>.
252b5132 6
f96b4a7b 7 This file is part of the GNU Binutils.
252b5132 8
f96b4a7b 9 This program is free software; you can redistribute it and/or modify
3ec57632 10 it under the terms of the GNU General Public License as published by
f96b4a7b
NC
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
252b5132 13
f96b4a7b 14 This program is distributed in the hope that it will be useful,
3ec57632
NC
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
252b5132 18
3ec57632 19 You should have received a copy of the GNU General Public License
f96b4a7b
NC
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
22 MA 02110-1301, USA. */
23
252b5132 24
8c95a62e 25/* This module is in charge of working out the contents of expressions.
252b5132 26
8c95a62e
KH
27 It has to keep track of the relative/absness of a symbol etc. This
28 is done by keeping all values in a struct (an etree_value_type)
29 which contains a value, a section to which it is relative and a
30 valid bit. */
252b5132 31
252b5132 32#include "sysdep.h"
3db64b00 33#include "bfd.h"
252b5132
RH
34#include "bfdlink.h"
35
36#include "ld.h"
37#include "ldmain.h"
38#include "ldmisc.h"
39#include "ldexp.h"
f856040a 40#include "ldlex.h"
df2a7313 41#include <ldgram.h>
252b5132 42#include "ldlang.h"
c7d701b0 43#include "libiberty.h"
2c382fb6 44#include "safe-ctype.h"
252b5132 45
e9ee469a 46static void exp_fold_tree_1 (etree_type *);
e9ee469a 47static bfd_vma align_n (bfd_vma, bfd_vma);
2d20f7bf 48
ba916c8a
MM
49segment_type *segments;
50
e9ee469a 51struct ldexp_control expld;
fbbb9ac5 52
7b17f854 53/* Print the string representation of the given token. Surround it
b34976b6 54 with spaces if INFIX_P is TRUE. */
7b17f854 55
252b5132 56static void
1579bae1 57exp_print_token (token_code_type code, int infix_p)
252b5132 58{
4da711b1 59 static const struct
c7d701b0 60 {
8c95a62e 61 token_code_type code;
c7d701b0
NC
62 char * name;
63 }
64 table[] =
65 {
8c95a62e 66 { INT, "int" },
8c95a62e
KH
67 { NAME, "NAME" },
68 { PLUSEQ, "+=" },
69 { MINUSEQ, "-=" },
70 { MULTEQ, "*=" },
71 { DIVEQ, "/=" },
72 { LSHIFTEQ, "<<=" },
73 { RSHIFTEQ, ">>=" },
74 { ANDEQ, "&=" },
75 { OREQ, "|=" },
76 { OROR, "||" },
77 { ANDAND, "&&" },
78 { EQ, "==" },
79 { NE, "!=" },
80 { LE, "<=" },
81 { GE, ">=" },
82 { LSHIFT, "<<" },
7cecdbff 83 { RSHIFT, ">>" },
8c95a62e
KH
84 { ALIGN_K, "ALIGN" },
85 { BLOCK, "BLOCK" },
c7d701b0
NC
86 { QUAD, "QUAD" },
87 { SQUAD, "SQUAD" },
88 { LONG, "LONG" },
89 { SHORT, "SHORT" },
90 { BYTE, "BYTE" },
8c95a62e
KH
91 { SECTIONS, "SECTIONS" },
92 { SIZEOF_HEADERS, "SIZEOF_HEADERS" },
8c95a62e
KH
93 { MEMORY, "MEMORY" },
94 { DEFINED, "DEFINED" },
95 { TARGET_K, "TARGET" },
96 { SEARCH_DIR, "SEARCH_DIR" },
97 { MAP, "MAP" },
8c95a62e 98 { ENTRY, "ENTRY" },
c7d701b0 99 { NEXT, "NEXT" },
362c1d1a 100 { ALIGNOF, "ALIGNOF" },
c7d701b0
NC
101 { SIZEOF, "SIZEOF" },
102 { ADDR, "ADDR" },
103 { LOADADDR, "LOADADDR" },
24718e3b 104 { CONSTANT, "CONSTANT" },
8c0848b5
AM
105 { ABSOLUTE, "ABSOLUTE" },
106 { MAX_K, "MAX" },
107 { MIN_K, "MIN" },
108 { ASSERT_K, "ASSERT" },
1049f94e 109 { REL, "relocatable" },
2d20f7bf 110 { DATA_SEGMENT_ALIGN, "DATA_SEGMENT_ALIGN" },
8c37241b 111 { DATA_SEGMENT_RELRO_END, "DATA_SEGMENT_RELRO_END" },
ba916c8a 112 { DATA_SEGMENT_END, "DATA_SEGMENT_END" },
3ec57632
NC
113 { ORIGIN, "ORIGIN" },
114 { LENGTH, "LENGTH" },
ba916c8a 115 { SEGMENT_START, "SEGMENT_START" }
8c95a62e 116 };
252b5132
RH
117 unsigned int idx;
118
7b17f854
RS
119 for (idx = 0; idx < ARRAY_SIZE (table); idx++)
120 if (table[idx].code == code)
121 break;
c7d701b0 122
7b17f854
RS
123 if (infix_p)
124 fputc (' ', config.map_file);
125
126 if (idx < ARRAY_SIZE (table))
127 fputs (table[idx].name, config.map_file);
128 else if (code < 127)
129 fputc (code, config.map_file);
c7d701b0 130 else
7b17f854
RS
131 fprintf (config.map_file, "<code %d>", code);
132
133 if (infix_p)
134 fputc (' ', config.map_file);
252b5132
RH
135}
136
4de2d33d 137static void
e9ee469a 138make_abs (void)
252b5132 139{
7542af2a
AM
140 if (expld.result.section != NULL)
141 expld.result.value += expld.result.section->vma;
e9ee469a 142 expld.result.section = bfd_abs_section_ptr;
252b5132
RH
143}
144
e9ee469a 145static void
1579bae1 146new_abs (bfd_vma value)
252b5132 147{
e9ee469a
AM
148 expld.result.valid_p = TRUE;
149 expld.result.section = bfd_abs_section_ptr;
150 expld.result.value = value;
151 expld.result.str = NULL;
252b5132
RH
152}
153
252b5132 154etree_type *
1579bae1 155exp_intop (bfd_vma value)
252b5132 156{
d3ce72d0
NC
157 etree_type *new_e = (etree_type *) stat_alloc (sizeof (new_e->value));
158 new_e->type.node_code = INT;
159 new_e->type.lineno = lineno;
160 new_e->value.value = value;
161 new_e->value.str = NULL;
162 new_e->type.node_class = etree_value;
163 return new_e;
2c382fb6 164}
252b5132 165
2c382fb6 166etree_type *
1579bae1 167exp_bigintop (bfd_vma value, char *str)
2c382fb6 168{
d3ce72d0
NC
169 etree_type *new_e = (etree_type *) stat_alloc (sizeof (new_e->value));
170 new_e->type.node_code = INT;
171 new_e->type.lineno = lineno;
172 new_e->value.value = value;
173 new_e->value.str = str;
174 new_e->type.node_class = etree_value;
175 return new_e;
252b5132
RH
176}
177
1049f94e 178/* Build an expression representing an unnamed relocatable value. */
252b5132
RH
179
180etree_type *
1579bae1 181exp_relop (asection *section, bfd_vma value)
252b5132 182{
d3ce72d0
NC
183 etree_type *new_e = (etree_type *) stat_alloc (sizeof (new_e->rel));
184 new_e->type.node_code = REL;
185 new_e->type.lineno = lineno;
186 new_e->type.node_class = etree_rel;
187 new_e->rel.section = section;
188 new_e->rel.value = value;
189 return new_e;
252b5132
RH
190}
191
7542af2a
AM
192static void
193new_number (bfd_vma value)
194{
195 expld.result.valid_p = TRUE;
196 expld.result.value = value;
197 expld.result.str = NULL;
198 expld.result.section = NULL;
199}
200
e9ee469a 201static void
5942515f 202new_rel (bfd_vma value, asection *section)
252b5132 203{
e9ee469a
AM
204 expld.result.valid_p = TRUE;
205 expld.result.value = value;
5942515f 206 expld.result.str = NULL;
e9ee469a 207 expld.result.section = section;
252b5132
RH
208}
209
e9ee469a
AM
210static void
211new_rel_from_abs (bfd_vma value)
252b5132 212{
e9ee469a
AM
213 expld.result.valid_p = TRUE;
214 expld.result.value = value - expld.section->vma;
215 expld.result.str = NULL;
216 expld.result.section = expld.section;
252b5132
RH
217}
218
e9ee469a
AM
219static void
220fold_unary (etree_type *tree)
0ae1cf52 221{
e9ee469a
AM
222 exp_fold_tree_1 (tree->unary.child);
223 if (expld.result.valid_p)
0ae1cf52
AM
224 {
225 switch (tree->type.node_code)
226 {
227 case ALIGN_K:
e9ee469a 228 if (expld.phase != lang_first_phase_enum)
dea2f0a8 229 new_rel_from_abs (align_n (expld.dot, expld.result.value));
0ae1cf52 230 else
e9ee469a 231 expld.result.valid_p = FALSE;
0ae1cf52
AM
232 break;
233
234 case ABSOLUTE:
e9ee469a 235 make_abs ();
0ae1cf52
AM
236 break;
237
238 case '~':
e9ee469a 239 expld.result.value = ~expld.result.value;
0ae1cf52
AM
240 break;
241
242 case '!':
e9ee469a 243 expld.result.value = !expld.result.value;
0ae1cf52
AM
244 break;
245
246 case '-':
e9ee469a 247 expld.result.value = -expld.result.value;
0ae1cf52
AM
248 break;
249
250 case NEXT:
251 /* Return next place aligned to value. */
e9ee469a 252 if (expld.phase != lang_first_phase_enum)
0ae1cf52 253 {
e9ee469a
AM
254 make_abs ();
255 expld.result.value = align_n (expld.dot, expld.result.value);
0ae1cf52
AM
256 }
257 else
e9ee469a 258 expld.result.valid_p = FALSE;
0ae1cf52
AM
259 break;
260
261 case DATA_SEGMENT_END:
ea7c2e6c
AM
262 if (expld.phase == lang_first_phase_enum
263 || expld.section != bfd_abs_section_ptr)
0ae1cf52 264 {
ea7c2e6c
AM
265 expld.result.valid_p = FALSE;
266 }
267 else if (expld.dataseg.phase == exp_dataseg_align_seen
268 || expld.dataseg.phase == exp_dataseg_relro_seen)
269 {
270 expld.dataseg.phase = exp_dataseg_end_seen;
271 expld.dataseg.end = expld.result.value;
272 }
273 else if (expld.dataseg.phase == exp_dataseg_done
274 || expld.dataseg.phase == exp_dataseg_adjust
275 || expld.dataseg.phase == exp_dataseg_relro_adjust)
276 {
277 /* OK. */
0ae1cf52
AM
278 }
279 else
e9ee469a 280 expld.result.valid_p = FALSE;
0ae1cf52
AM
281 break;
282
283 default:
284 FAIL ();
285 break;
286 }
287 }
0ae1cf52
AM
288}
289
e9ee469a
AM
290static void
291fold_binary (etree_type *tree)
252b5132 292{
4ac0c898 293 etree_value_type lhs;
e9ee469a 294 exp_fold_tree_1 (tree->binary.lhs);
ba916c8a
MM
295
296 /* The SEGMENT_START operator is special because its first
8c0848b5
AM
297 operand is a string, not the name of a symbol. Note that the
298 operands have been swapped, so binary.lhs is second (default)
299 operand, binary.rhs is first operand. */
e9ee469a 300 if (expld.result.valid_p && tree->type.node_code == SEGMENT_START)
ba916c8a
MM
301 {
302 const char *segment_name;
303 segment_type *seg;
7542af2a 304
ba916c8a
MM
305 /* Check to see if the user has overridden the default
306 value. */
307 segment_name = tree->binary.rhs->name.name;
308 for (seg = segments; seg; seg = seg->next)
309 if (strcmp (seg->name, segment_name) == 0)
310 {
c8ce5710
L
311 if (!seg->used
312 && config.magic_demand_paged
313 && (seg->value % config.maxpagesize) != 0)
314 einfo (_("%P: warning: address of `%s' isn't multiple of maximum page size\n"),
315 segment_name);
ba916c8a 316 seg->used = TRUE;
7542af2a 317 new_rel_from_abs (seg->value);
ba916c8a
MM
318 break;
319 }
4ac0c898 320 return;
ba916c8a 321 }
252b5132 322
4ac0c898
AM
323 lhs = expld.result;
324 exp_fold_tree_1 (tree->binary.rhs);
325 expld.result.valid_p &= lhs.valid_p;
326
327 if (expld.result.valid_p)
328 {
7542af2a 329 if (lhs.section != expld.result.section)
252b5132 330 {
7542af2a
AM
331 /* If the values are from different sections, and neither is
332 just a number, make both the source arguments absolute. */
333 if (expld.result.section != NULL
334 && lhs.section != NULL)
335 {
336 make_abs ();
337 lhs.value += lhs.section->vma;
338 }
339
340 /* If the rhs is just a number, keep the lhs section. */
341 else if (expld.result.section == NULL)
342 expld.result.section = lhs.section;
4ac0c898 343 }
252b5132 344
4ac0c898
AM
345 switch (tree->type.node_code)
346 {
347 case '%':
348 if (expld.result.value != 0)
349 expld.result.value = ((bfd_signed_vma) lhs.value
350 % (bfd_signed_vma) expld.result.value);
351 else if (expld.phase != lang_mark_phase_enum)
352 einfo (_("%F%S %% by zero\n"));
353 break;
252b5132 354
4ac0c898
AM
355 case '/':
356 if (expld.result.value != 0)
357 expld.result.value = ((bfd_signed_vma) lhs.value
358 / (bfd_signed_vma) expld.result.value);
359 else if (expld.phase != lang_mark_phase_enum)
360 einfo (_("%F%S / by zero\n"));
361 break;
252b5132 362
e9ee469a 363#define BOP(x, y) \
7542af2a
AM
364 case x: \
365 expld.result.value = lhs.value y expld.result.value; \
366 break;
367
368#define BOPN(x, y) \
369 case x: \
370 expld.result.value = lhs.value y expld.result.value; \
371 expld.result.section = NULL; \
372 break;
e9ee469a 373
4ac0c898
AM
374 BOP ('+', +);
375 BOP ('*', *);
376 BOP ('-', -);
377 BOP (LSHIFT, <<);
378 BOP (RSHIFT, >>);
4ac0c898
AM
379 BOP ('&', &);
380 BOP ('^', ^);
381 BOP ('|', |);
7542af2a
AM
382 BOPN (EQ, ==);
383 BOPN (NE, !=);
384 BOPN ('<', <);
385 BOPN ('>', >);
386 BOPN (LE, <=);
387 BOPN (GE, >=);
388 BOPN (ANDAND, &&);
389 BOPN (OROR, ||);
4ac0c898
AM
390
391 case MAX_K:
392 if (lhs.value > expld.result.value)
393 expld.result.value = lhs.value;
394 break;
252b5132 395
4ac0c898
AM
396 case MIN_K:
397 if (lhs.value < expld.result.value)
398 expld.result.value = lhs.value;
399 break;
252b5132 400
4ac0c898
AM
401 case ALIGN_K:
402 expld.result.value = align_n (lhs.value, expld.result.value);
403 break;
c468c8bc 404
4ac0c898
AM
405 case DATA_SEGMENT_ALIGN:
406 expld.dataseg.relro = exp_dataseg_relro_start;
ea7c2e6c
AM
407 if (expld.phase == lang_first_phase_enum
408 || expld.section != bfd_abs_section_ptr)
409 expld.result.valid_p = FALSE;
410 else
4ac0c898
AM
411 {
412 bfd_vma maxpage = lhs.value;
413 bfd_vma commonpage = expld.result.value;
2d20f7bf 414
4ac0c898
AM
415 expld.result.value = align_n (expld.dot, maxpage);
416 if (expld.dataseg.phase == exp_dataseg_relro_adjust)
417 expld.result.value = expld.dataseg.base;
ea7c2e6c
AM
418 else if (expld.dataseg.phase == exp_dataseg_adjust)
419 {
420 if (commonpage < maxpage)
421 expld.result.value += ((expld.dot + commonpage - 1)
422 & (maxpage - commonpage));
423 }
424 else
4ac0c898
AM
425 {
426 expld.result.value += expld.dot & (maxpage - 1);
ea7c2e6c
AM
427 if (expld.dataseg.phase == exp_dataseg_done)
428 {
429 /* OK. */
430 }
431 else if (expld.dataseg.phase == exp_dataseg_none)
2d20f7bf 432 {
4ac0c898
AM
433 expld.dataseg.phase = exp_dataseg_align_seen;
434 expld.dataseg.min_base = expld.dot;
435 expld.dataseg.base = expld.result.value;
436 expld.dataseg.pagesize = commonpage;
437 expld.dataseg.maxpagesize = maxpage;
438 expld.dataseg.relro_end = 0;
2d20f7bf 439 }
ea7c2e6c
AM
440 else
441 expld.result.valid_p = FALSE;
2d20f7bf 442 }
4ac0c898 443 }
4ac0c898 444 break;
e9ee469a 445
4ac0c898
AM
446 case DATA_SEGMENT_RELRO_END:
447 expld.dataseg.relro = exp_dataseg_relro_end;
ea7c2e6c
AM
448 if (expld.phase == lang_first_phase_enum
449 || expld.section != bfd_abs_section_ptr)
450 expld.result.valid_p = FALSE;
451 else if (expld.dataseg.phase == exp_dataseg_align_seen
452 || expld.dataseg.phase == exp_dataseg_adjust
453 || expld.dataseg.phase == exp_dataseg_relro_adjust
454 || expld.dataseg.phase == exp_dataseg_done)
4ac0c898
AM
455 {
456 if (expld.dataseg.phase == exp_dataseg_align_seen
457 || expld.dataseg.phase == exp_dataseg_relro_adjust)
458 expld.dataseg.relro_end = lhs.value + expld.result.value;
e9ee469a 459
4ac0c898
AM
460 if (expld.dataseg.phase == exp_dataseg_relro_adjust
461 && (expld.dataseg.relro_end
462 & (expld.dataseg.pagesize - 1)))
463 {
464 expld.dataseg.relro_end += expld.dataseg.pagesize - 1;
465 expld.dataseg.relro_end &= ~(expld.dataseg.pagesize - 1);
466 expld.result.value = (expld.dataseg.relro_end
467 - expld.result.value);
a4f5ad88
JJ
468 }
469 else
4ac0c898 470 expld.result.value = lhs.value;
a4f5ad88 471
4ac0c898
AM
472 if (expld.dataseg.phase == exp_dataseg_align_seen)
473 expld.dataseg.phase = exp_dataseg_relro_seen;
252b5132 474 }
4ac0c898
AM
475 else
476 expld.result.valid_p = FALSE;
477 break;
478
479 default:
480 FAIL ();
252b5132 481 }
252b5132 482 }
252b5132
RH
483}
484
e9ee469a
AM
485static void
486fold_trinary (etree_type *tree)
0ae1cf52 487{
e9ee469a
AM
488 exp_fold_tree_1 (tree->trinary.cond);
489 if (expld.result.valid_p)
490 exp_fold_tree_1 (expld.result.value
491 ? tree->trinary.lhs
492 : tree->trinary.rhs);
0ae1cf52
AM
493}
494
e9ee469a
AM
495static void
496fold_name (etree_type *tree)
252b5132 497{
e9ee469a 498 memset (&expld.result, 0, sizeof (expld.result));
c468c8bc 499
4de2d33d 500 switch (tree->type.node_code)
8c95a62e
KH
501 {
502 case SIZEOF_HEADERS:
e9ee469a
AM
503 if (expld.phase != lang_first_phase_enum)
504 {
505 bfd_vma hdr_size = 0;
506 /* Don't find the real header size if only marking sections;
507 The bfd function may cache incorrect data. */
508 if (expld.phase != lang_mark_phase_enum)
f13a99db 509 hdr_size = bfd_sizeof_headers (link_info.output_bfd, &link_info);
7542af2a 510 new_number (hdr_size);
e9ee469a 511 }
8c95a62e 512 break;
67469e1f 513
8c95a62e 514 case DEFINED:
e759c116 515 expld.uses_defined = TRUE;
e9ee469a 516 if (expld.phase == lang_first_phase_enum)
1b493742 517 lang_track_definedness (tree->name.name);
8c95a62e
KH
518 else
519 {
520 struct bfd_link_hash_entry *h;
420e579c
HPN
521 int def_iteration
522 = lang_symbol_definition_iteration (tree->name.name);
8c95a62e 523
f13a99db
AM
524 h = bfd_wrapped_link_hash_lookup (link_info.output_bfd,
525 &link_info,
8c95a62e 526 tree->name.name,
b34976b6 527 FALSE, FALSE, TRUE);
7542af2a
AM
528 new_number (h != NULL
529 && (h->type == bfd_link_hash_defined
530 || h->type == bfd_link_hash_defweak
531 || h->type == bfd_link_hash_common)
532 && (def_iteration == lang_statement_iteration
533 || def_iteration == -1));
8c95a62e
KH
534 }
535 break;
67469e1f 536
8c95a62e 537 case NAME:
e9ee469a
AM
538 if (expld.phase == lang_first_phase_enum)
539 ;
540 else if (tree->name.name[0] == '.' && tree->name.name[1] == 0)
541 new_rel_from_abs (expld.dot);
542 else
8c95a62e
KH
543 {
544 struct bfd_link_hash_entry *h;
545
f13a99db
AM
546 h = bfd_wrapped_link_hash_lookup (link_info.output_bfd,
547 &link_info,
8c95a62e 548 tree->name.name,
1b493742
NS
549 TRUE, FALSE, TRUE);
550 if (!h)
551 einfo (_("%P%F: bfd_link_hash_lookup failed: %E\n"));
552 else if (h->type == bfd_link_hash_defined
553 || h->type == bfd_link_hash_defweak)
8c95a62e 554 {
7542af2a 555 asection *output_section;
8c95a62e 556
7542af2a
AM
557 output_section = h->u.def.section->output_section;
558 if (output_section == NULL)
559 {
560 if (expld.phase != lang_mark_phase_enum)
561 einfo (_("%X%S: unresolvable symbol `%s'"
562 " referenced in expression\n"),
563 tree->name.name);
8c95a62e 564 }
5c3049d2
AM
565 else if (output_section == bfd_abs_section_ptr
566 && (expld.section != bfd_abs_section_ptr
567 || ld_compatibility >= 221))
abf4be64 568 new_number (h->u.def.value + h->u.def.section->output_offset);
7542af2a
AM
569 else
570 new_rel (h->u.def.value + h->u.def.section->output_offset,
571 output_section);
8c95a62e 572 }
e9ee469a
AM
573 else if (expld.phase == lang_final_phase_enum
574 || expld.assigning_to_dot)
8c95a62e
KH
575 einfo (_("%F%S: undefined symbol `%s' referenced in expression\n"),
576 tree->name.name);
1b493742
NS
577 else if (h->type == bfd_link_hash_new)
578 {
579 h->type = bfd_link_hash_undefined;
580 h->u.undef.abfd = NULL;
3eda52aa 581 if (h->u.undef.next == NULL && h != link_info.hash->undefs_tail)
a010d60f 582 bfd_link_add_undef (link_info.hash, h);
1b493742 583 }
8c95a62e
KH
584 }
585 break;
586
587 case ADDR:
e9ee469a 588 if (expld.phase != lang_first_phase_enum)
8c95a62e
KH
589 {
590 lang_output_section_statement_type *os;
591
592 os = lang_output_section_find (tree->name.name);
cc3e2771
NS
593 if (os == NULL)
594 {
595 if (expld.phase == lang_final_phase_enum)
596 einfo (_("%F%S: undefined section `%s' referenced in expression\n"),
597 tree->name.name);
598 }
599 else if (os->processed_vma)
5942515f 600 new_rel (0, os->bfd_section);
8c95a62e 601 }
8c95a62e
KH
602 break;
603
604 case LOADADDR:
e9ee469a 605 if (expld.phase != lang_first_phase_enum)
8c95a62e
KH
606 {
607 lang_output_section_statement_type *os;
608
609 os = lang_output_section_find (tree->name.name);
cc3e2771
NS
610 if (os == NULL)
611 {
612 if (expld.phase == lang_final_phase_enum)
613 einfo (_("%F%S: undefined section `%s' referenced in expression\n"),
614 tree->name.name);
615 }
616 else if (os->processed_lma)
1b493742 617 {
e9ee469a 618 if (os->load_base == NULL)
3e23777d 619 new_abs (os->bfd_section->lma);
e9ee469a 620 else
67469e1f
AM
621 {
622 exp_fold_tree_1 (os->load_base);
819da74e
AM
623 if (expld.result.valid_p)
624 make_abs ();
67469e1f 625 }
1b493742 626 }
8c95a62e 627 }
8c95a62e
KH
628 break;
629
630 case SIZEOF:
362c1d1a 631 case ALIGNOF:
e9ee469a 632 if (expld.phase != lang_first_phase_enum)
8c95a62e 633 {
8c95a62e
KH
634 lang_output_section_statement_type *os;
635
636 os = lang_output_section_find (tree->name.name);
5397b1fe 637 if (os == NULL)
cc3e2771
NS
638 {
639 if (expld.phase == lang_final_phase_enum)
640 einfo (_("%F%S: undefined section `%s' referenced in expression\n"),
641 tree->name.name);
7542af2a 642 new_number (0);
cc3e2771 643 }
cde9e0be 644 else if (os->processed_vma)
362c1d1a
NS
645 {
646 bfd_vma val;
647
648 if (tree->type.node_code == SIZEOF)
f13a99db
AM
649 val = (os->bfd_section->size
650 / bfd_octets_per_byte (link_info.output_bfd));
362c1d1a
NS
651 else
652 val = (bfd_vma)1 << os->bfd_section->alignment_power;
653
7542af2a 654 new_number (val);
362c1d1a 655 }
8c95a62e 656 }
8c95a62e
KH
657 break;
658
3ec57632
NC
659 case LENGTH:
660 {
661 lang_memory_region_type *mem;
662
663 mem = lang_memory_region_lookup (tree->name.name, FALSE);
664 if (mem != NULL)
7542af2a 665 new_number (mem->length);
3ec57632 666 else
e9ee469a
AM
667 einfo (_("%F%S: undefined MEMORY region `%s'"
668 " referenced in expression\n"), tree->name.name);
3ec57632
NC
669 }
670 break;
671
672 case ORIGIN:
7542af2a
AM
673 if (expld.phase != lang_first_phase_enum)
674 {
675 lang_memory_region_type *mem;
3ec57632 676
7542af2a
AM
677 mem = lang_memory_region_lookup (tree->name.name, FALSE);
678 if (mem != NULL)
679 new_rel_from_abs (mem->origin);
680 else
681 einfo (_("%F%S: undefined MEMORY region `%s'"
682 " referenced in expression\n"), tree->name.name);
683 }
3ec57632
NC
684 break;
685
24718e3b
L
686 case CONSTANT:
687 if (strcmp (tree->name.name, "MAXPAGESIZE") == 0)
7542af2a 688 new_number (config.maxpagesize);
24718e3b 689 else if (strcmp (tree->name.name, "COMMONPAGESIZE") == 0)
7542af2a 690 new_number (config.commonpagesize);
24718e3b
L
691 else
692 einfo (_("%F%S: unknown constant `%s' referenced in expression\n"),
693 tree->name.name);
694 break;
695
8c95a62e
KH
696 default:
697 FAIL ();
698 break;
699 }
252b5132 700}
8c95a62e 701
e9ee469a
AM
702static void
703exp_fold_tree_1 (etree_type *tree)
252b5132 704{
252b5132
RH
705 if (tree == NULL)
706 {
e9ee469a
AM
707 memset (&expld.result, 0, sizeof (expld.result));
708 return;
252b5132
RH
709 }
710
4de2d33d 711 switch (tree->type.node_class)
252b5132
RH
712 {
713 case etree_value:
5c3049d2
AM
714 if (expld.section == bfd_abs_section_ptr
715 && ld_compatibility < 221)
716 new_abs (tree->value.value);
717 else
718 new_number (tree->value.value);
5942515f 719 expld.result.str = tree->value.str;
252b5132
RH
720 break;
721
722 case etree_rel:
e9ee469a
AM
723 if (expld.phase != lang_first_phase_enum)
724 {
725 asection *output_section = tree->rel.section->output_section;
726 new_rel (tree->rel.value + tree->rel.section->output_offset,
5942515f 727 output_section);
e9ee469a 728 }
252b5132 729 else
e9ee469a 730 memset (&expld.result, 0, sizeof (expld.result));
252b5132
RH
731 break;
732
733 case etree_assert:
e9ee469a 734 exp_fold_tree_1 (tree->assert_s.child);
5397b1fe
AM
735 if (expld.phase == lang_final_phase_enum && !expld.result.value)
736 einfo ("%X%P: %s\n", tree->assert_s.message);
252b5132
RH
737 break;
738
739 case etree_unary:
e9ee469a 740 fold_unary (tree);
252b5132
RH
741 break;
742
743 case etree_binary:
e9ee469a 744 fold_binary (tree);
252b5132 745 break;
0ae1cf52
AM
746
747 case etree_trinary:
e9ee469a 748 fold_trinary (tree);
0ae1cf52 749 break;
252b5132
RH
750
751 case etree_assign:
752 case etree_provide:
b46a87b1 753 case etree_provided:
252b5132
RH
754 if (tree->assign.dst[0] == '.' && tree->assign.dst[1] == 0)
755 {
c7d701b0 756 /* Assignment to dot can only be done during allocation. */
b46a87b1 757 if (tree->type.node_class != etree_assign)
252b5132 758 einfo (_("%F%S can not PROVIDE assignment to location counter\n"));
e9ee469a
AM
759 if (expld.phase == lang_mark_phase_enum
760 || expld.phase == lang_allocating_phase_enum
761 || (expld.phase == lang_final_phase_enum
762 && expld.section == bfd_abs_section_ptr))
252b5132 763 {
fbbb9ac5 764 /* Notify the folder that this is an assignment to dot. */
e9ee469a
AM
765 expld.assigning_to_dot = TRUE;
766 exp_fold_tree_1 (tree->assign.src);
767 expld.assigning_to_dot = FALSE;
768
769 if (!expld.result.valid_p)
770 {
771 if (expld.phase != lang_mark_phase_enum)
772 einfo (_("%F%S invalid assignment to location counter\n"));
773 }
774 else if (expld.dotp == NULL)
775 einfo (_("%F%S assignment to location counter"
776 " invalid outside of SECTION\n"));
252b5132
RH
777 else
778 {
e9ee469a
AM
779 bfd_vma nextdot;
780
7542af2a
AM
781 nextdot = expld.result.value;
782 if (expld.result.section != NULL)
783 nextdot += expld.result.section->vma;
784 else
785 nextdot += expld.section->vma;
e9ee469a
AM
786 if (nextdot < expld.dot
787 && expld.section != bfd_abs_section_ptr)
788 einfo (_("%F%S cannot move location counter backwards"
789 " (from %V to %V)\n"), expld.dot, nextdot);
252b5132
RH
790 else
791 {
e9ee469a
AM
792 expld.dot = nextdot;
793 *expld.dotp = nextdot;
252b5132
RH
794 }
795 }
796 }
8b3d8fa8 797 else
e9ee469a 798 memset (&expld.result, 0, sizeof (expld.result));
252b5132
RH
799 }
800 else
801 {
e9ee469a 802 struct bfd_link_hash_entry *h = NULL;
252b5132 803
e9ee469a
AM
804 if (tree->type.node_class == etree_provide)
805 {
252b5132 806 h = bfd_link_hash_lookup (link_info.hash, tree->assign.dst,
e9ee469a
AM
807 FALSE, FALSE, TRUE);
808 if (h == NULL
809 || (h->type != bfd_link_hash_new
810 && h->type != bfd_link_hash_undefined
811 && h->type != bfd_link_hash_common))
812 {
813 /* Do nothing. The symbol was never referenced, or was
814 defined by some object. */
815 break;
816 }
817 }
818
819 exp_fold_tree_1 (tree->assign.src);
e759c116
AM
820 if (expld.result.valid_p
821 || (expld.phase == lang_first_phase_enum
822 && !expld.uses_defined))
e9ee469a 823 {
1579bae1 824 if (h == NULL)
67010b46 825 {
e9ee469a
AM
826 h = bfd_link_hash_lookup (link_info.hash, tree->assign.dst,
827 TRUE, FALSE, TRUE);
828 if (h == NULL)
67010b46
NC
829 einfo (_("%P%F:%s: hash creation failed\n"),
830 tree->assign.dst);
831 }
e9ee469a
AM
832
833 /* FIXME: Should we worry if the symbol is already
834 defined? */
835 lang_update_definedness (tree->assign.dst, h);
836 h->type = bfd_link_hash_defined;
837 h->u.def.value = expld.result.value;
7542af2a
AM
838 if (expld.result.section == NULL)
839 expld.result.section = expld.section;
e9ee469a
AM
840 h->u.def.section = expld.result.section;
841 if (tree->type.node_class == etree_provide)
842 tree->type.node_class = etree_provided;
1338dd10
PB
843
844 /* Copy the symbol type if this is a simple assignment of
845 one symbol to annother. */
846 if (tree->assign.src->type.node_class == etree_name)
847 {
848 struct bfd_link_hash_entry *hsrc;
849
850 hsrc = bfd_link_hash_lookup (link_info.hash,
851 tree->assign.src->name.name,
852 FALSE, FALSE, TRUE);
853 if (hsrc)
854 bfd_copy_link_hash_symbol_type (link_info.output_bfd, h,
855 hsrc);
856 }
252b5132 857 }
e092cb30
AM
858 else if (expld.phase == lang_final_phase_enum)
859 {
860 h = bfd_link_hash_lookup (link_info.hash, tree->assign.dst,
861 FALSE, FALSE, TRUE);
862 if (h != NULL
863 && h->type == bfd_link_hash_new)
864 h->type = bfd_link_hash_undefined;
865 }
252b5132
RH
866 }
867 break;
868
869 case etree_name:
e9ee469a 870 fold_name (tree);
252b5132
RH
871 break;
872
873 default:
874 FAIL ();
e9ee469a 875 memset (&expld.result, 0, sizeof (expld.result));
252b5132
RH
876 break;
877 }
252b5132
RH
878}
879
e9ee469a
AM
880void
881exp_fold_tree (etree_type *tree, asection *current_section, bfd_vma *dotp)
75ff4589 882{
e9ee469a
AM
883 expld.dot = *dotp;
884 expld.dotp = dotp;
885 expld.section = current_section;
e759c116 886 expld.uses_defined = FALSE;
e9ee469a 887 exp_fold_tree_1 (tree);
75ff4589
L
888}
889
e759c116 890void
e9ee469a 891exp_fold_tree_no_dot (etree_type *tree)
252b5132 892{
e9ee469a
AM
893 expld.dot = 0;
894 expld.dotp = NULL;
895 expld.section = bfd_abs_section_ptr;
e759c116 896 expld.uses_defined = FALSE;
e9ee469a 897 exp_fold_tree_1 (tree);
252b5132
RH
898}
899
900etree_type *
1579bae1 901exp_binop (int code, etree_type *lhs, etree_type *rhs)
252b5132 902{
d3ce72d0 903 etree_type value, *new_e;
252b5132
RH
904
905 value.type.node_code = code;
f856040a 906 value.type.lineno = lhs->type.lineno;
252b5132
RH
907 value.binary.lhs = lhs;
908 value.binary.rhs = rhs;
909 value.type.node_class = etree_binary;
e9ee469a
AM
910 exp_fold_tree_no_dot (&value);
911 if (expld.result.valid_p)
912 return exp_intop (expld.result.value);
913
d3ce72d0
NC
914 new_e = (etree_type *) stat_alloc (sizeof (new_e->binary));
915 memcpy (new_e, &value, sizeof (new_e->binary));
916 return new_e;
252b5132
RH
917}
918
919etree_type *
1579bae1 920exp_trinop (int code, etree_type *cond, etree_type *lhs, etree_type *rhs)
252b5132 921{
d3ce72d0 922 etree_type value, *new_e;
e9ee469a 923
252b5132 924 value.type.node_code = code;
f856040a 925 value.type.lineno = lhs->type.lineno;
252b5132
RH
926 value.trinary.lhs = lhs;
927 value.trinary.cond = cond;
928 value.trinary.rhs = rhs;
929 value.type.node_class = etree_trinary;
e9ee469a
AM
930 exp_fold_tree_no_dot (&value);
931 if (expld.result.valid_p)
932 return exp_intop (expld.result.value);
c7d701b0 933
d3ce72d0
NC
934 new_e = (etree_type *) stat_alloc (sizeof (new_e->trinary));
935 memcpy (new_e, &value, sizeof (new_e->trinary));
936 return new_e;
252b5132
RH
937}
938
252b5132 939etree_type *
1579bae1 940exp_unop (int code, etree_type *child)
252b5132 941{
d3ce72d0 942 etree_type value, *new_e;
252b5132 943
252b5132 944 value.unary.type.node_code = code;
f856040a 945 value.unary.type.lineno = child->type.lineno;
252b5132
RH
946 value.unary.child = child;
947 value.unary.type.node_class = etree_unary;
e9ee469a
AM
948 exp_fold_tree_no_dot (&value);
949 if (expld.result.valid_p)
950 return exp_intop (expld.result.value);
c7d701b0 951
d3ce72d0
NC
952 new_e = (etree_type *) stat_alloc (sizeof (new_e->unary));
953 memcpy (new_e, &value, sizeof (new_e->unary));
954 return new_e;
252b5132
RH
955}
956
252b5132 957etree_type *
1579bae1 958exp_nameop (int code, const char *name)
252b5132 959{
d3ce72d0 960 etree_type value, *new_e;
e9ee469a 961
252b5132 962 value.name.type.node_code = code;
f856040a 963 value.name.type.lineno = lineno;
252b5132
RH
964 value.name.name = name;
965 value.name.type.node_class = etree_name;
966
e9ee469a
AM
967 exp_fold_tree_no_dot (&value);
968 if (expld.result.valid_p)
969 return exp_intop (expld.result.value);
c7d701b0 970
d3ce72d0
NC
971 new_e = (etree_type *) stat_alloc (sizeof (new_e->name));
972 memcpy (new_e, &value, sizeof (new_e->name));
973 return new_e;
252b5132
RH
974
975}
976
2e57b2af
AM
977static etree_type *
978exp_assop (const char *dst,
979 etree_type *src,
980 enum node_tree_enum class,
981 bfd_boolean hidden)
252b5132
RH
982{
983 etree_type *n;
984
1e9cc1c2 985 n = (etree_type *) stat_alloc (sizeof (n->assign));
252b5132 986 n->assign.type.node_code = '=';
f856040a 987 n->assign.type.lineno = src->type.lineno;
2e57b2af 988 n->assign.type.node_class = class;
252b5132
RH
989 n->assign.src = src;
990 n->assign.dst = dst;
7af8e998 991 n->assign.hidden = hidden;
252b5132
RH
992 return n;
993}
994
2e57b2af
AM
995etree_type *
996exp_assign (const char *dst, etree_type *src)
997{
998 return exp_assop (dst, src, etree_assign, FALSE);
999}
1000
1001etree_type *
1002exp_defsym (const char *dst, etree_type *src)
1003{
1004 return exp_assop (dst, src, etree_assign, TRUE);
1005}
1006
1007/* Handle PROVIDE. */
1008
1009etree_type *
1010exp_provide (const char *dst, etree_type *src, bfd_boolean hidden)
1011{
1012 return exp_assop (dst, src, etree_provide, hidden);
1013}
1014
252b5132
RH
1015/* Handle ASSERT. */
1016
1017etree_type *
1579bae1 1018exp_assert (etree_type *exp, const char *message)
252b5132
RH
1019{
1020 etree_type *n;
1021
1e9cc1c2 1022 n = (etree_type *) stat_alloc (sizeof (n->assert_s));
252b5132 1023 n->assert_s.type.node_code = '!';
f856040a 1024 n->assert_s.type.lineno = exp->type.lineno;
252b5132
RH
1025 n->assert_s.type.node_class = etree_assert;
1026 n->assert_s.child = exp;
1027 n->assert_s.message = message;
1028 return n;
1029}
1030
4de2d33d 1031void
1579bae1 1032exp_print_tree (etree_type *tree)
252b5132 1033{
ae78bbeb
AM
1034 bfd_boolean function_like;
1035
c7d701b0
NC
1036 if (config.map_file == NULL)
1037 config.map_file = stderr;
b7a26f91 1038
c7d701b0
NC
1039 if (tree == NULL)
1040 {
1041 minfo ("NULL TREE\n");
1042 return;
1043 }
b7a26f91 1044
8c95a62e
KH
1045 switch (tree->type.node_class)
1046 {
1047 case etree_value:
1048 minfo ("0x%v", tree->value.value);
1049 return;
1050 case etree_rel:
1051 if (tree->rel.section->owner != NULL)
1052 minfo ("%B:", tree->rel.section->owner);
1053 minfo ("%s+0x%v", tree->rel.section->name, tree->rel.value);
1054 return;
1055 case etree_assign:
ae78bbeb 1056 fputs (tree->assign.dst, config.map_file);
b34976b6 1057 exp_print_token (tree->type.node_code, TRUE);
8c95a62e
KH
1058 exp_print_tree (tree->assign.src);
1059 break;
1060 case etree_provide:
b46a87b1 1061 case etree_provided:
8c95a62e
KH
1062 fprintf (config.map_file, "PROVIDE (%s, ", tree->assign.dst);
1063 exp_print_tree (tree->assign.src);
ae78bbeb 1064 fputc (')', config.map_file);
8c95a62e
KH
1065 break;
1066 case etree_binary:
ae78bbeb
AM
1067 function_like = FALSE;
1068 switch (tree->type.node_code)
1069 {
1070 case MAX_K:
1071 case MIN_K:
1072 case ALIGN_K:
1073 case DATA_SEGMENT_ALIGN:
1074 case DATA_SEGMENT_RELRO_END:
1075 function_like = TRUE;
1076 }
1077 if (function_like)
1078 {
1079 exp_print_token (tree->type.node_code, FALSE);
1080 fputc (' ', config.map_file);
1081 }
1082 fputc ('(', config.map_file);
8c95a62e 1083 exp_print_tree (tree->binary.lhs);
ae78bbeb
AM
1084 if (function_like)
1085 fprintf (config.map_file, ", ");
1086 else
1087 exp_print_token (tree->type.node_code, TRUE);
8c95a62e 1088 exp_print_tree (tree->binary.rhs);
ae78bbeb 1089 fputc (')', config.map_file);
8c95a62e
KH
1090 break;
1091 case etree_trinary:
1092 exp_print_tree (tree->trinary.cond);
ae78bbeb 1093 fputc ('?', config.map_file);
8c95a62e 1094 exp_print_tree (tree->trinary.lhs);
ae78bbeb 1095 fputc (':', config.map_file);
8c95a62e
KH
1096 exp_print_tree (tree->trinary.rhs);
1097 break;
1098 case etree_unary:
b34976b6 1099 exp_print_token (tree->unary.type.node_code, FALSE);
8c95a62e
KH
1100 if (tree->unary.child)
1101 {
7b17f854 1102 fprintf (config.map_file, " (");
8c95a62e 1103 exp_print_tree (tree->unary.child);
ae78bbeb 1104 fputc (')', config.map_file);
8c95a62e
KH
1105 }
1106 break;
1107
1108 case etree_assert:
1109 fprintf (config.map_file, "ASSERT (");
1110 exp_print_tree (tree->assert_s.child);
1111 fprintf (config.map_file, ", %s)", tree->assert_s.message);
1112 break;
1113
8c95a62e
KH
1114 case etree_name:
1115 if (tree->type.node_code == NAME)
ae78bbeb 1116 fputs (tree->name.name, config.map_file);
8c95a62e
KH
1117 else
1118 {
b34976b6 1119 exp_print_token (tree->type.node_code, FALSE);
8c95a62e 1120 if (tree->name.name)
7b17f854 1121 fprintf (config.map_file, " (%s)", tree->name.name);
8c95a62e
KH
1122 }
1123 break;
1124 default:
1125 FAIL ();
1126 break;
252b5132 1127 }
252b5132
RH
1128}
1129
1130bfd_vma
e9ee469a 1131exp_get_vma (etree_type *tree, bfd_vma def, char *name)
252b5132 1132{
252b5132
RH
1133 if (tree != NULL)
1134 {
e9ee469a
AM
1135 exp_fold_tree_no_dot (tree);
1136 if (expld.result.valid_p)
1137 return expld.result.value;
1138 else if (name != NULL && expld.phase != lang_mark_phase_enum)
c58dea77 1139 einfo (_("%F%S: nonconstant expression for %s\n"), name);
252b5132 1140 }
e9ee469a 1141 return def;
252b5132
RH
1142}
1143
4de2d33d 1144int
e9ee469a 1145exp_get_value_int (etree_type *tree, int def, char *name)
252b5132 1146{
e9ee469a 1147 return exp_get_vma (tree, def, name);
252b5132
RH
1148}
1149
2c382fb6 1150fill_type *
e9ee469a 1151exp_get_fill (etree_type *tree, fill_type *def, char *name)
2c382fb6
AM
1152{
1153 fill_type *fill;
2c382fb6
AM
1154 size_t len;
1155 unsigned int val;
1156
1157 if (tree == NULL)
1158 return def;
1159
e9ee469a
AM
1160 exp_fold_tree_no_dot (tree);
1161 if (!expld.result.valid_p)
1162 {
1163 if (name != NULL && expld.phase != lang_mark_phase_enum)
c58dea77 1164 einfo (_("%F%S: nonconstant expression for %s\n"), name);
e9ee469a
AM
1165 return def;
1166 }
2c382fb6 1167
e9ee469a 1168 if (expld.result.str != NULL && (len = strlen (expld.result.str)) != 0)
2c382fb6
AM
1169 {
1170 unsigned char *dst;
1171 unsigned char *s;
1e9cc1c2 1172 fill = (fill_type *) xmalloc ((len + 1) / 2 + sizeof (*fill) - 1);
2c382fb6
AM
1173 fill->size = (len + 1) / 2;
1174 dst = fill->data;
e9ee469a 1175 s = (unsigned char *) expld.result.str;
2c382fb6
AM
1176 val = 0;
1177 do
1178 {
1179 unsigned int digit;
1180
1181 digit = *s++ - '0';
1182 if (digit > 9)
1183 digit = (digit - 'A' + '0' + 10) & 0xf;
1184 val <<= 4;
1185 val += digit;
1186 --len;
1187 if ((len & 1) == 0)
1188 {
1189 *dst++ = val;
1190 val = 0;
1191 }
1192 }
1193 while (len != 0);
1194 }
1195 else
1196 {
1e9cc1c2 1197 fill = (fill_type *) xmalloc (4 + sizeof (*fill) - 1);
e9ee469a 1198 val = expld.result.value;
2c382fb6
AM
1199 fill->data[0] = (val >> 24) & 0xff;
1200 fill->data[1] = (val >> 16) & 0xff;
1201 fill->data[2] = (val >> 8) & 0xff;
1202 fill->data[3] = (val >> 0) & 0xff;
1203 fill->size = 4;
1204 }
1205 return fill;
1206}
1207
252b5132 1208bfd_vma
e9ee469a 1209exp_get_abs_int (etree_type *tree, int def, char *name)
252b5132 1210{
e9ee469a
AM
1211 if (tree != NULL)
1212 {
1213 exp_fold_tree_no_dot (tree);
c7d701b0 1214
e9ee469a
AM
1215 if (expld.result.valid_p)
1216 {
7542af2a
AM
1217 if (expld.result.section != NULL)
1218 expld.result.value += expld.result.section->vma;
e9ee469a
AM
1219 return expld.result.value;
1220 }
1221 else if (name != NULL && expld.phase != lang_mark_phase_enum)
f856040a
L
1222 {
1223 lineno = tree->type.lineno;
1224 einfo (_("%F%S: nonconstant expression for %s\n"), name);
1225 }
e9ee469a
AM
1226 }
1227 return def;
252b5132 1228}
c553bb91 1229
e5caa5e0
AM
1230static bfd_vma
1231align_n (bfd_vma value, bfd_vma align)
c553bb91
AM
1232{
1233 if (align <= 1)
1234 return value;
1235
1236 value = (value + align - 1) / align;
1237 return value * align;
1238}