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