This commit was generated by cvs2svn to track changes on a CVS vendor
[external/binutils.git] / ld / ldexp.c
1 /* This module handles expression trees.
2 Copyright (C) 1991, 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
3 Written by Steve Chamberlain of Cygnus Support (sac@cygnus.com).
4
5 This file is part of GLD, the Gnu Linker.
6
7 GLD is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
11
12 GLD is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GLD; see the file COPYING.  If not, write to
19 the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
20
21 /*
22 This module is in charge of working out the contents of expressions.
23
24 It has to keep track of the relative/absness of a symbol etc. This is
25 done by keeping all values in a struct (an etree_value_type) which
26 contains a value, a section to which it is relative and a valid bit.
27
28 */
29
30
31 #include "bfd.h"
32 #include "sysdep.h"
33 #include "bfdlink.h"
34
35 #include "ld.h"
36 #include "ldmain.h"
37 #include "ldmisc.h"
38 #include "ldexp.h"
39 #include "ldgram.h"
40 #include "ldlang.h"
41
42 static void exp_print_token PARAMS ((token_code_type code));
43 static void make_abs PARAMS ((etree_value_type *ptr));
44 static etree_value_type new_abs PARAMS ((bfd_vma value));
45 static void check PARAMS ((lang_output_section_statement_type *os,
46                            const char *name, const char *op));
47 static etree_value_type new_rel
48   PARAMS ((bfd_vma value, lang_output_section_statement_type *section));
49 static etree_value_type new_rel_from_section
50   PARAMS ((bfd_vma value, lang_output_section_statement_type *section));
51 static etree_value_type fold_binary
52   PARAMS ((etree_type *tree,
53            lang_output_section_statement_type *current_section,
54            lang_phase_type allocation_done,
55            bfd_vma dot, bfd_vma *dotp));
56 static etree_value_type fold_name
57   PARAMS ((etree_type *tree,
58            lang_output_section_statement_type *current_section,
59            lang_phase_type allocation_done,
60            bfd_vma dot));
61 static etree_value_type exp_fold_tree_no_dot
62   PARAMS ((etree_type *tree,
63            lang_output_section_statement_type *current_section,
64            lang_phase_type allocation_done));
65
66 static void
67 exp_print_token (code)
68      token_code_type code;
69 {
70   static CONST struct
71     {
72       token_code_type code;
73       char *name;
74     } table[] =
75       {
76         { INT,  "int" },
77         { REL, "relocateable" },
78         { NAME,"NAME" },
79         { PLUSEQ,"+=" },
80         { MINUSEQ,"-=" },
81         { MULTEQ,"*=" },
82         { DIVEQ,"/=" },
83         { LSHIFTEQ,"<<=" },
84         { RSHIFTEQ,">>=" },
85         { ANDEQ,"&=" },
86         { OREQ,"|=" },
87         { OROR,"||" },
88         { ANDAND,"&&" },
89         { EQ,"==" },
90         { NE,"!=" },
91         { LE,"<=" },
92         { GE,">=" },
93         { LSHIFT,"<<" },
94         { RSHIFT,">>=" },
95         { ALIGN_K,"ALIGN" },
96         { BLOCK,"BLOCK" },
97         { SECTIONS,"SECTIONS" },
98         { SIZEOF_HEADERS,"SIZEOF_HEADERS" },
99         { NEXT,"NEXT" },
100         { SIZEOF,"SIZEOF" },
101         { ADDR,"ADDR" },
102         { LOADADDR,"LOADADDR" },
103         { MEMORY,"MEMORY" },
104         { DEFINED,"DEFINED" },
105         { TARGET_K,"TARGET" },
106         { SEARCH_DIR,"SEARCH_DIR" },
107         { MAP,"MAP" },
108         { QUAD,"QUAD" },
109         { LONG,"LONG" },
110         { SHORT,"SHORT" },
111         { BYTE,"BYTE" },
112         { ENTRY,"ENTRY" },
113         { 0,(char *)NULL }
114       };
115   unsigned int idx;
116
117   for (idx = 0; table[idx].name != (char*)NULL; idx++) {
118     if (table[idx].code == code) {
119       fprintf(config.map_file, "%s", table[idx].name);
120       return;
121     }
122   }
123   /* Not in table, just print it alone */
124   fprintf(config.map_file, "%c",code);
125 }
126
127 static void 
128 make_abs (ptr)
129      etree_value_type *ptr;
130 {
131     asection *s = ptr->section->bfd_section;
132     ptr->value += s->vma;
133     ptr->section = abs_output_section;
134 }
135
136 static etree_value_type
137 new_abs (value)
138      bfd_vma value;
139 {
140   etree_value_type new;
141   new.valid = true;
142   new.section = abs_output_section;
143   new.value = value;
144   return new;
145 }
146
147 static void 
148 check (os, name, op)
149      lang_output_section_statement_type *os;
150      const char *name;
151      const char *op;
152 {
153   if (os == NULL)
154     einfo ("%F%P: %s uses undefined section %s\n", op, name);
155   if (! os->processed)
156     einfo ("%F%P: %s forward reference of section %s\n", op, name);
157 }
158
159 etree_type *
160 exp_intop (value)
161      bfd_vma value;
162 {
163   etree_type *new = (etree_type *) stat_alloc(sizeof(new->value));
164   new->type.node_code = INT;
165   new->value.value = value;
166   new->type.node_class = etree_value;
167   return new;
168
169 }
170
171 /* Build an expression representing an unnamed relocateable value.  */
172
173 etree_type *
174 exp_relop (section, value)
175      asection *section;
176      bfd_vma value;
177 {
178   etree_type *new = (etree_type *) stat_alloc (sizeof (new->rel));
179   new->type.node_code = REL;
180   new->type.node_class = etree_rel;
181   new->rel.section = section;
182   new->rel.value = value;
183   return new;
184 }
185
186 static etree_value_type
187 new_rel (value, section)
188      bfd_vma value;
189      lang_output_section_statement_type *section;
190 {
191   etree_value_type new;
192   new.valid = true;
193   new.value = value;
194   new.section = section;
195   return new;
196 }
197
198 static etree_value_type
199 new_rel_from_section (value, section)
200      bfd_vma value;
201      lang_output_section_statement_type *section;
202 {
203   etree_value_type new;
204   new.valid = true;
205   new.value = value;
206   new.section = section;
207
208     new.value -= section->bfd_section->vma;
209
210   return new;
211 }
212
213 static etree_value_type 
214 fold_binary (tree, current_section, allocation_done, dot, dotp)
215      etree_type *tree;
216      lang_output_section_statement_type *current_section;
217      lang_phase_type allocation_done;
218      bfd_vma dot;
219      bfd_vma *dotp;
220 {
221   etree_value_type result;
222
223   result = exp_fold_tree (tree->binary.lhs, current_section,
224                           allocation_done, dot, dotp);
225   if (result.valid)
226     {
227       etree_value_type other;
228
229       other = exp_fold_tree (tree->binary.rhs,
230                              current_section,
231                              allocation_done, dot,dotp) ;
232       if (other.valid)
233         {
234           /* If the values are from different sections, or this is an
235              absolute expression, make both the source arguments
236              absolute.  However, adding or subtracting an absolute
237              value from a relative value is meaningful, and is an
238              exception.  */
239           if (current_section != abs_output_section
240               && (other.section == abs_output_section
241                   || (result.section == abs_output_section
242                       && tree->type.node_code == '+'))
243               && (tree->type.node_code == '+'
244                   || tree->type.node_code == '-'))
245             {
246               etree_value_type hold;
247
248               /* If there is only one absolute term, make sure it is the
249                  second one.  */
250               if (other.section != abs_output_section)
251                 {
252                   hold = result;
253                   result = other;
254                   other = hold;
255                 }
256             }
257           else if (result.section != other.section
258                    || current_section == abs_output_section)
259             {
260               make_abs(&result);
261               make_abs(&other);
262             }
263
264           switch (tree->type.node_code) 
265             {
266             case '%':
267               if (other.value == 0)
268                 einfo ("%F%S %% by zero\n");
269               result.value = ((bfd_signed_vma) result.value
270                               % (bfd_signed_vma) other.value);
271               break;
272
273             case '/':
274               if (other.value == 0)
275                 einfo ("%F%S / by zero\n");
276               result.value = ((bfd_signed_vma) result.value
277                               / (bfd_signed_vma) other.value);
278               break;
279
280 #define BOP(x,y) case x : result.value = result.value y other.value; break;
281               BOP('+',+);
282               BOP('*',*);
283               BOP('-',-);
284               BOP(LSHIFT,<<);
285               BOP(RSHIFT,>>);
286               BOP(EQ,==);
287               BOP(NE,!=);
288               BOP('<',<);
289               BOP('>',>);
290               BOP(LE,<=);
291               BOP(GE,>=);
292               BOP('&',&);
293               BOP('^',^);
294               BOP('|',|);
295               BOP(ANDAND,&&);
296               BOP(OROR,||);
297
298             default:
299               FAIL();
300             }
301         }
302       else
303         {
304           result.valid = false;
305         }
306     }
307
308   return result;
309 }
310
311 etree_value_type 
312 invalid ()
313 {
314   etree_value_type new;
315   new.valid = false;
316   return new;
317 }
318
319 static etree_value_type 
320 fold_name (tree, current_section, allocation_done, dot)
321      etree_type *tree;
322      lang_output_section_statement_type *current_section;
323      lang_phase_type  allocation_done;
324      bfd_vma dot;
325 {
326   etree_value_type result;
327   switch (tree->type.node_code) 
328       {
329       case SIZEOF_HEADERS:
330         if (allocation_done != lang_first_phase_enum) 
331           {
332             result = new_abs ((bfd_vma)
333                               bfd_sizeof_headers (output_bfd,
334                                                   link_info.relocateable));
335           }
336         else
337           {
338             result.valid = false;
339           }
340         break;
341       case DEFINED:
342         if (allocation_done == lang_first_phase_enum)
343           result.valid = false;
344         else
345           {
346             struct bfd_link_hash_entry *h;
347
348             h = bfd_wrapped_link_hash_lookup (output_bfd, &link_info,
349                                               tree->name.name,
350                                               false, false, true);
351             result.value = (h != (struct bfd_link_hash_entry *) NULL
352                             && (h->type == bfd_link_hash_defined
353                                 || h->type == bfd_link_hash_defweak
354                                 || h->type == bfd_link_hash_common));
355             result.section = 0;
356             result.valid = true;
357           }
358         break;
359       case NAME:
360         result.valid = false;
361         if (tree->name.name[0] == '.' && tree->name.name[1] == 0)
362           {
363             if (allocation_done != lang_first_phase_enum)
364               result = new_rel_from_section(dot, current_section);
365             else
366               result = invalid();
367           }
368         else if (allocation_done != lang_first_phase_enum)
369           {
370             struct bfd_link_hash_entry *h;
371
372             h = bfd_wrapped_link_hash_lookup (output_bfd, &link_info,
373                                               tree->name.name,
374                                               false, false, true);
375             if (h != NULL
376                 && (h->type == bfd_link_hash_defined
377                     || h->type == bfd_link_hash_defweak))
378               {
379                 if (bfd_is_abs_section (h->u.def.section))
380                   result = new_abs (h->u.def.value);
381                 else if (allocation_done == lang_final_phase_enum
382                          || allocation_done == lang_allocating_phase_enum)
383                   {
384                     lang_output_section_statement_type *os;
385                 
386                     os = (lang_output_section_statement_lookup
387                           (h->u.def.section->output_section->name));
388
389                     /* FIXME: Is this correct if this section is being
390                        linked with -R?  */
391                     result = new_rel ((h->u.def.value
392                                        + h->u.def.section->output_offset),
393                                       os);
394                   }
395               }
396             else if (allocation_done == lang_final_phase_enum)
397               einfo ("%F%S: undefined symbol `%s' referenced in expression\n",
398                      tree->name.name);
399           }
400         break;
401
402       case ADDR:
403         if (allocation_done != lang_first_phase_enum)
404           {
405             lang_output_section_statement_type *os;
406
407             os = lang_output_section_find (tree->name.name);
408             check (os, tree->name.name, "ADDR");
409             result = new_rel (0, os);
410           }
411         else
412           result = invalid ();
413         break;
414
415       case LOADADDR:
416         if (allocation_done != lang_first_phase_enum)
417           {
418             lang_output_section_statement_type *os;
419
420             os = lang_output_section_find (tree->name.name);
421             check (os, tree->name.name, "LOADADDR");
422             if (os->load_base == NULL)
423               result = new_rel (0, os);
424             else
425               result = exp_fold_tree_no_dot (os->load_base,
426                                              abs_output_section,
427                                              allocation_done);
428           }
429         else
430           result = invalid ();
431         break;
432
433       case SIZEOF:
434         if (allocation_done != lang_first_phase_enum)
435           {
436             lang_output_section_statement_type *os;
437
438             os = lang_output_section_find (tree->name.name);
439             check (os, tree->name.name, "SIZEOF");
440             result = new_abs (os->bfd_section->_raw_size);
441           }
442         else
443           result = invalid ();
444         break;
445
446       default:
447         FAIL();
448         break;
449       }
450
451   return result;
452 }
453 etree_value_type 
454 exp_fold_tree (tree, current_section, allocation_done, dot, dotp)
455      etree_type *tree;
456      lang_output_section_statement_type *current_section;
457      lang_phase_type  allocation_done;
458      bfd_vma dot;
459      bfd_vma *dotp;
460 {
461   etree_value_type result;
462
463   if (tree == NULL)
464     {
465       result.valid = false;
466       return result;
467     }
468
469   switch (tree->type.node_class) 
470     {
471     case etree_value:
472       result = new_rel (tree->value.value, current_section);
473       break;
474
475     case etree_rel:
476       if (allocation_done != lang_final_phase_enum)
477         result.valid = false;
478       else
479         result = new_rel ((tree->rel.value
480                            + tree->rel.section->output_section->vma
481                            + tree->rel.section->output_offset),
482                           current_section);
483       break;
484
485     case etree_unary:
486       result = exp_fold_tree (tree->unary.child,
487                               current_section,
488                               allocation_done, dot, dotp);
489       if (result.valid)
490         {
491           switch (tree->type.node_code) 
492             {
493             case ALIGN_K:
494               if (allocation_done != lang_first_phase_enum)
495                 result = new_rel_from_section (ALIGN_N (dot, result.value),
496                                                current_section);
497               else
498                 result.valid = false;
499               break;
500
501             case ABSOLUTE:
502               if (allocation_done != lang_first_phase_enum && result.valid)
503                 {
504                   result.value += result.section->bfd_section->vma;
505                   result.section = abs_output_section;
506                 }
507               else 
508                 result.valid = false;
509               break;
510
511             case '~':
512               make_abs (&result);
513               result.value = ~result.value;
514               break;
515
516             case '!':
517               make_abs (&result);
518               result.value = !result.value;
519               break;
520
521             case '-':
522               make_abs (&result);
523               result.value = -result.value;
524               break;
525
526             case NEXT:
527               /* Return next place aligned to value.  */
528               if (allocation_done == lang_allocating_phase_enum)
529                 {
530                   make_abs (&result);
531                   result.value = ALIGN_N (dot, result.value);
532                 }
533               else
534                 result.valid = false;
535               break;
536
537             default:
538               FAIL ();
539               break;
540             }
541         }
542       break;
543
544     case etree_trinary:
545       result = exp_fold_tree (tree->trinary.cond, current_section,
546                               allocation_done, dot, dotp);
547       if (result.valid)
548         result = exp_fold_tree ((result.value
549                                  ? tree->trinary.lhs
550                                  : tree->trinary.rhs),
551                                 current_section,
552                                 allocation_done, dot, dotp);
553       break;
554
555     case etree_binary:
556       result = fold_binary (tree, current_section, allocation_done,
557                             dot, dotp);
558       break;
559
560     case etree_assign:
561     case etree_provide:
562       if (tree->assign.dst[0] == '.' && tree->assign.dst[1] == 0)
563         {
564           /* Assignment to dot can only be done during allocation */
565           if (tree->type.node_class == etree_provide)
566             einfo ("%F%S can not PROVIDE assignment to location counter\n");
567           if (allocation_done == lang_allocating_phase_enum
568               || (allocation_done == lang_final_phase_enum
569                   && current_section == abs_output_section))
570             {
571               result = exp_fold_tree (tree->assign.src,
572                                       current_section,
573                                       lang_allocating_phase_enum, dot,
574                                       dotp);
575               if (! result.valid)
576                 einfo ("%F%S invalid assignment to location counter\n");
577               else
578                 {
579                   if (current_section == NULL)
580                     einfo ("%F%S assignment to location counter invalid outside of SECTION\n");
581                   else
582                     {
583                       bfd_vma nextdot;
584
585                       nextdot = (result.value
586                                  + current_section->bfd_section->vma);
587                       if (nextdot < dot
588                           && current_section != abs_output_section)
589                         {
590                           einfo ("%F%S cannot move location counter backwards (from %V to %V)\n",
591                                  dot, nextdot);
592                         }
593                       else
594                         *dotp = nextdot; 
595                     }
596                 }
597             }
598         }
599       else
600         {
601           result = exp_fold_tree (tree->assign.src,
602                                   current_section, allocation_done,
603                                   dot, dotp);
604           if (result.valid)
605             {
606               boolean create;
607               struct bfd_link_hash_entry *h;
608
609               if (tree->type.node_class == etree_assign)
610                 create = true;
611               else
612                 create = false;
613               h = bfd_link_hash_lookup (link_info.hash, tree->assign.dst,
614                                         create, false, false);
615               if (h == (struct bfd_link_hash_entry *) NULL)
616                 {
617                   if (tree->type.node_class == etree_assign)
618                     einfo ("%P%F:%s: hash creation failed\n",
619                            tree->assign.dst);
620                 }
621               else if (tree->type.node_class == etree_provide
622                        && h->type != bfd_link_hash_undefined
623                        && h->type != bfd_link_hash_common)
624                 {
625                   /* Do nothing.  The symbol was defined by some
626                      object.  */
627                 }
628               else
629                 {
630                   /* FIXME: Should we worry if the symbol is already
631                      defined?  */
632                   h->type = bfd_link_hash_defined;
633                   h->u.def.value = result.value;
634                   h->u.def.section = result.section->bfd_section;
635                 }
636             }
637         }
638       break;
639
640     case etree_name:
641       result = fold_name (tree, current_section, allocation_done, dot);
642       break;
643
644     default:
645       FAIL ();
646       break;
647     }
648
649   return result;
650 }
651
652 static etree_value_type 
653 exp_fold_tree_no_dot (tree, current_section, allocation_done)
654      etree_type *tree;
655      lang_output_section_statement_type *current_section;
656      lang_phase_type allocation_done;
657 {
658 return exp_fold_tree(tree, current_section, allocation_done, (bfd_vma)
659                      0, (bfd_vma *)NULL);
660 }
661
662 etree_type *
663 exp_binop (code, lhs, rhs)
664      int code;
665      etree_type *lhs;
666      etree_type *rhs;
667 {
668   etree_type value, *new;
669   etree_value_type r;
670
671   value.type.node_code = code;
672   value.binary.lhs = lhs;
673   value.binary.rhs = rhs;
674   value.type.node_class = etree_binary;
675   r = exp_fold_tree_no_dot(&value,
676                            abs_output_section,
677                            lang_first_phase_enum );
678   if (r.valid)
679     {
680       return exp_intop(r.value);
681     }
682   new = (etree_type *) stat_alloc (sizeof (new->binary));
683   memcpy((char *)new, (char *)&value, sizeof(new->binary));
684   return new;
685 }
686
687 etree_type *
688 exp_trinop (code, cond, lhs, rhs)
689      int code;
690      etree_type *cond;
691      etree_type *lhs;
692      etree_type *rhs;
693 {
694   etree_type value, *new;
695   etree_value_type r;
696   value.type.node_code = code;
697   value.trinary.lhs = lhs;
698   value.trinary.cond = cond;
699   value.trinary.rhs = rhs;
700   value.type.node_class = etree_trinary;
701   r= exp_fold_tree_no_dot(&value,  (lang_output_section_statement_type
702                                     *)NULL,lang_first_phase_enum);
703   if (r.valid) {
704     return exp_intop(r.value);
705   }
706   new = (etree_type *) stat_alloc (sizeof (new->trinary));
707   memcpy((char *)new,(char *) &value, sizeof(new->trinary));
708   return new;
709 }
710
711
712 etree_type *
713 exp_unop (code, child)
714      int code;
715      etree_type *child;
716 {
717   etree_type value, *new;
718
719   etree_value_type r;
720   value.unary.type.node_code = code;
721   value.unary.child = child;
722   value.unary.type.node_class = etree_unary;
723   r = exp_fold_tree_no_dot(&value,abs_output_section,
724                            lang_first_phase_enum);
725   if (r.valid) {
726     return exp_intop(r.value);
727   }
728   new = (etree_type *) stat_alloc (sizeof (new->unary));
729   memcpy((char *)new, (char *)&value, sizeof(new->unary));
730   return new;
731 }
732
733
734 etree_type *
735 exp_nameop (code, name)
736      int code;
737      CONST char *name;
738 {
739   etree_type value, *new;
740   etree_value_type r;
741   value.name.type.node_code = code;
742   value.name.name = name;
743   value.name.type.node_class = etree_name;
744
745
746   r = exp_fold_tree_no_dot(&value,
747                            (lang_output_section_statement_type *)NULL,
748                            lang_first_phase_enum);
749   if (r.valid) {
750     return exp_intop(r.value);
751   }
752   new = (etree_type *) stat_alloc (sizeof (new->name));
753   memcpy((char *)new, (char *)&value, sizeof(new->name));
754   return new;
755
756 }
757
758
759
760
761 etree_type *
762 exp_assop (code, dst, src)
763      int code;
764      CONST char *dst;
765      etree_type *src;
766 {
767   etree_type value, *new;
768
769   value.assign.type.node_code = code;
770
771
772   value.assign.src = src;
773   value.assign.dst = dst;
774   value.assign.type.node_class = etree_assign;
775
776 #if 0
777   if (exp_fold_tree_no_dot(&value, &result)) {
778     return exp_intop(result);
779   }
780 #endif
781   new = (etree_type*) stat_alloc (sizeof (new->assign));
782   memcpy((char *)new, (char *)&value, sizeof(new->assign));
783   return new;
784 }
785
786 /* Handle PROVIDE.  */
787
788 etree_type *
789 exp_provide (dst, src)
790      const char *dst;
791      etree_type *src;
792 {
793   etree_type *n;
794
795   n = (etree_type *) stat_alloc (sizeof (n->assign));
796   n->assign.type.node_code = '=';
797   n->assign.type.node_class = etree_provide;
798   n->assign.src = src;
799   n->assign.dst = dst;
800   return n;
801 }
802
803 void 
804 exp_print_tree (tree)
805      etree_type *tree;
806 {
807   switch (tree->type.node_class) {
808   case etree_value:
809     minfo ("0x%v", tree->value.value);
810     return;
811   case etree_rel:
812     if (tree->rel.section->owner != NULL)
813       minfo ("%B:", tree->rel.section->owner);
814     minfo ("%s+0x%v", tree->rel.section->name, tree->rel.value);
815     return;
816   case etree_assign:
817 #if 0
818     if (tree->assign.dst->sdefs != (asymbol *)NULL){
819       fprintf(config.map_file,"%s (%x) ",tree->assign.dst->name,
820               tree->assign.dst->sdefs->value);
821     }
822     else {
823       fprintf(config.map_file,"%s (UNDEFINED)",tree->assign.dst->name);
824     }
825 #endif
826     fprintf(config.map_file,"%s",tree->assign.dst);
827     exp_print_token(tree->type.node_code);
828     exp_print_tree(tree->assign.src);
829     break;
830   case etree_provide:
831     fprintf (config.map_file, "PROVIDE (%s, ", tree->assign.dst);
832     exp_print_tree (tree->assign.src);
833     fprintf (config.map_file, ")");
834     break;
835   case etree_binary:
836     fprintf(config.map_file,"(");
837     exp_print_tree(tree->binary.lhs);
838     exp_print_token(tree->type.node_code);
839     exp_print_tree(tree->binary.rhs);
840     fprintf(config.map_file,")");
841     break;
842   case etree_trinary:
843     exp_print_tree(tree->trinary.cond);
844     fprintf(config.map_file,"?");
845     exp_print_tree(tree->trinary.lhs);
846     fprintf(config.map_file,":");
847     exp_print_tree(tree->trinary.rhs);
848     break;
849   case etree_unary:
850     exp_print_token(tree->unary.type.node_code);
851     if (tree->unary.child) 
852     {
853       
854     fprintf(config.map_file,"(");
855     exp_print_tree(tree->unary.child);
856     fprintf(config.map_file,")");
857   }
858     
859     break;
860   case etree_undef:
861     fprintf(config.map_file,"????????");
862     break;
863   case etree_name:
864     if (tree->type.node_code == NAME) {
865       fprintf(config.map_file,"%s", tree->name.name);
866     }
867     else {
868       exp_print_token(tree->type.node_code);
869       if (tree->name.name)
870       fprintf(config.map_file,"(%s)", tree->name.name);
871     }
872     break;
873   default:
874     FAIL();
875     break;
876   }
877 }
878
879 bfd_vma
880 exp_get_vma (tree, def, name, allocation_done)
881      etree_type *tree;
882      bfd_vma def;
883      char *name;
884      lang_phase_type allocation_done;
885 {
886   etree_value_type r;
887
888   if (tree != NULL)
889     {
890       r = exp_fold_tree_no_dot (tree, abs_output_section, allocation_done);
891       if (! r.valid && name != NULL)
892         einfo ("%F%S nonconstant expression for %s\n", name);
893       return r.value;
894     }
895   else
896     return def;
897 }
898
899 int 
900 exp_get_value_int (tree,def,name, allocation_done)
901      etree_type *tree;
902      int def;
903      char *name;
904      lang_phase_type allocation_done;
905 {
906   return (int)exp_get_vma(tree,(bfd_vma)def,name, allocation_done);
907 }
908
909
910 bfd_vma
911 exp_get_abs_int (tree, def, name, allocation_done)
912      etree_type *tree;
913      int def;
914      char *name;
915      lang_phase_type allocation_done;
916 {
917   etree_value_type res;
918   res = exp_fold_tree_no_dot (tree, abs_output_section, allocation_done);
919
920   if (res.valid)
921     {
922       res.value += res.section->bfd_section->vma;
923     }
924   else {
925     einfo ("%F%S non constant expression for %s\n",name);
926   }
927   return res.value;
928 }