home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD2.mdf / gnu / djgpp / src / binutils.2 / ld / ldexp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-05-30  |  18.4 KB  |  825 lines

  1. /* This module handles expression trees.
  2. Copyright (C) 1991 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, 675 Mass Ave, Cambridge, MA 02139, 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.  
  34. #include "ld.h"
  35. #include "ldmain.h"
  36. #include "ldmisc.h"
  37. #include "ldexp.h"
  38. #include "ldgram.h"
  39. #include "ldsym.h"
  40. #include "ldlang.h"
  41.  
  42. extern char *output_filename;
  43. extern unsigned int undefined_global_sym_count;
  44. extern unsigned int defined_global_sym_count;
  45. extern bfd *output_bfd;
  46. extern bfd_size_type largest_section;
  47. extern lang_statement_list_type file_chain;
  48. extern args_type command_line;
  49. extern ld_config_type config;
  50.  
  51. extern lang_input_statement_type *script_file;
  52. extern unsigned int defined_global_sym_count;
  53.   extern lang_output_section_statement_type *abs_output_section;
  54. extern bfd_vma print_dot;
  55.  
  56.  
  57. static void
  58. DEFUN(exp_print_token,( code),
  59.       token_code_type code)
  60. {
  61.   static CONST struct  {
  62.     token_code_type code;
  63.     char *name;
  64.   } table[] =
  65.       {
  66.     INT,    "int",
  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,"<<",
  83.     RSHIFT,">>=",
  84.     ALIGN_K,"ALIGN",
  85.     BLOCK,"BLOCK",
  86.     SECTIONS,"SECTIONS",
  87.     SIZEOF_HEADERS,"SIZEOF_HEADERS",
  88.     NEXT,"NEXT",
  89.     SIZEOF,"SIZEOF",
  90.     ADDR,"ADDR",
  91.     MEMORY,"MEMORY",
  92.  
  93.  
  94.  
  95.  
  96.  
  97.     DEFINED,"DEFINED",
  98.     TARGET_K,"TARGET",
  99.     SEARCH_DIR,"SEARCH_DIR",
  100.     MAP,"MAP",
  101.     LONG,"LONG",
  102.     SHORT,"SHORT",
  103.     BYTE,"BYTE",
  104.     ENTRY,"ENTRY",
  105.     0,(char *)NULL} ;
  106.  
  107.  
  108.  
  109.   unsigned int idx;
  110.   for (idx = 0; table[idx].name != (char*)NULL; idx++) {
  111.     if (table[idx].code == code) {
  112.       fprintf(config.map_file, "%s", table[idx].name);
  113.       return;
  114.     }
  115.   }
  116.   /* Not in table, just print it alone */
  117.   fprintf(config.map_file, "%c",code);
  118. }
  119.  
  120. static void 
  121. DEFUN(make_abs,(ptr),
  122.       etree_value_type *ptr)
  123. {
  124.     asection *s = ptr->section->bfd_section;
  125.     ptr->value += s->vma;
  126.     ptr->section = abs_output_section;
  127. }
  128.  
  129. static
  130. DEFUN(etree_value_type new_abs,(value),
  131.       bfd_vma value)
  132. {
  133.  
  134.   
  135.   etree_value_type new;
  136.   new.valid = true;
  137.   new.section = abs_output_section;
  138.   new.value = value;
  139.   return new;
  140. }
  141.  
  142. static void 
  143. DEFUN(check, (os, name, op),
  144.       lang_output_section_statement_type *os AND
  145.       CONST char *name AND
  146.       CONST char *op)
  147. {
  148.   if (os == (lang_output_section_statement_type *)NULL) {
  149.     einfo("%F%P %s uses undefined section %s\n", op, name);
  150.   }
  151.   if (os->processed == false) {
  152.     einfo("%F%P %s forward reference of section %s\n",op, name);
  153.   }
  154. }
  155.  
  156. etree_type *
  157. DEFUN(exp_intop,(value),
  158.       bfd_vma value)
  159. {
  160.   etree_type *new = (etree_type *)stat_alloc((bfd_size_type)(sizeof(new->value)));
  161.   new->type.node_code = INT;
  162.   new->value.value = value;
  163.   new->type.node_class = etree_value;
  164.   return new;
  165.  
  166. }
  167.  
  168.  
  169. static
  170. DEFUN(etree_value_type new_rel,(value, section),
  171.       bfd_vma value AND
  172.       lang_output_section_statement_type *section)
  173. {
  174.   etree_value_type new;
  175.   new.valid = true;
  176.   new.value = value;
  177.   new.section = section;
  178.   return new;
  179. }
  180.  
  181. static
  182. DEFUN(etree_value_type
  183.       new_rel_from_section, (value, section),
  184.       bfd_vma value AND
  185.       lang_output_section_statement_type *section)
  186. {
  187.   etree_value_type new;
  188.   new.valid = true;
  189.   new.value = value;
  190.   new.section = section;
  191.  
  192.     new.value -= section->bfd_section->vma;
  193.  
  194.   return new;
  195. }
  196.  
  197. static etree_value_type 
  198. DEFUN(fold_binary,(tree, current_section, allocation_done, dot, dotp),
  199.       etree_type *tree AND
  200.       lang_output_section_statement_type *current_section AND
  201.       lang_phase_type  allocation_done AND
  202.       bfd_vma dot AND
  203.       bfd_vma *dotp)
  204. {
  205.   etree_value_type result;
  206.  
  207.   result =  exp_fold_tree(tree->binary.lhs,  current_section,
  208.               allocation_done, dot, dotp);
  209.   if (result.valid) {
  210.     etree_value_type other;
  211.     other = exp_fold_tree(tree->binary.rhs,
  212.               current_section,
  213.               allocation_done, dot,dotp) ;
  214.     if (other.valid) {
  215.     /* If values are from different sections, or this is an */
  216.     /* absolute expression, make both source args absolute */
  217.       if (result.section !=  other.section ||
  218.       current_section == abs_output_section) 
  219.       {
  220.     make_abs(&result);
  221.     make_abs(&other);
  222.       }
  223.       
  224.       switch (tree->type.node_code) 
  225.     {
  226.     case '%':
  227.       /* Mod,  both absolule*/
  228.  
  229.       if (other.value == 0) {
  230.         einfo("%F%S % by zero\n");
  231.       }
  232.       result.value = (int)result.value % (int)other.value;
  233.       break;
  234.     case '/':
  235.       if (other.value == 0) {
  236.         einfo("%F%S / by zero\n");
  237.       }
  238.       result.value = (int)result.value / (int) other.value;
  239.       break;
  240. #define BOP(x,y) case x : result.value = result.value y other.value;break;
  241.       BOP('+',+);
  242.       BOP('*',*);
  243.       BOP('-',-);
  244.       BOP(LSHIFT,<<);
  245.       BOP(RSHIFT,>>);
  246.       BOP(EQ,==);
  247.       BOP(NE,!=);
  248.       BOP('<',<);
  249.       BOP('>',>);
  250.       BOP(LE,<=);
  251.       BOP(GE,>=);
  252.       BOP('&',&);
  253.       BOP('^',^);
  254.       BOP('|',|);
  255.       BOP(ANDAND,&&);
  256.       BOP(OROR,||);
  257.     default:
  258.       FAIL();
  259.     }
  260.     }
  261.     else {
  262.       result.valid = false;
  263.     }
  264.   }
  265.   return result;
  266. }
  267. etree_value_type 
  268. DEFUN_VOID(invalid)
  269. {
  270.   etree_value_type new;
  271.   new.valid = false;
  272.   return new;
  273. }
  274.  
  275. etree_value_type 
  276. DEFUN(fold_name, (tree, current_section, allocation_done, dot),
  277.       etree_type *tree AND
  278.       lang_output_section_statement_type *current_section AND
  279.       lang_phase_type  allocation_done AND
  280.       bfd_vma dot)
  281. {
  282.   etree_value_type result;
  283.   switch (tree->type.node_code) 
  284.       {
  285.       case SIZEOF_HEADERS:
  286.     if (allocation_done != lang_first_phase_enum) 
  287.         {
  288.           result = new_abs(bfd_sizeof_headers(output_bfd,
  289.                         config.relocateable_output));
  290.  
  291.         }
  292.     else {
  293.       result.valid = false;
  294.     }
  295.     break;
  296.       case DEFINED:
  297.     result.value =
  298.       ldsym_get_soft(tree->name.name) != (ldsym_type *)NULL;
  299.     result.section = 0;
  300.     result.valid = true;
  301.     break;
  302.       case NAME:
  303.     result.valid = false;
  304.     if (tree->name.name[0] == '.' && tree->name.name[1] == 0) {
  305.  
  306.       if (allocation_done != lang_first_phase_enum) {
  307.         result = new_rel_from_section(dot, current_section);
  308.       }
  309.       else {
  310.         result = invalid();
  311.       }
  312.     }
  313.     else {
  314.       if (allocation_done == lang_final_phase_enum) {
  315.         ldsym_type *sy = ldsym_get_soft(tree->name.name);
  316.       
  317.         if (sy) {
  318.           asymbol **sdefp = sy->sdefs_chain;
  319.  
  320.           if (sdefp) {
  321.         asymbol *sdef = *sdefp;
  322. #if 0
  323.         if (sdef->section == (asection *)NULL) {
  324.           /* This is an absolute symbol */
  325.           result = new_abs(sdef->value);
  326.         }
  327.         else
  328. #endif
  329.  {
  330.           lang_output_section_statement_type *os =
  331.             lang_output_section_statement_lookup(
  332.                              sdef->section->output_section->name);
  333.           /* If the symbol is from a file which we are not
  334.              relocating (-R) then return an absolute for its
  335.              value */
  336.           if (bfd_asymbol_bfd(sdef)->usrdata && 
  337.               ((lang_input_statement_type*)(bfd_asymbol_bfd(sdef)->usrdata))->just_syms_flag == true) 
  338.               {
  339.             result = new_abs(sdef->value +sdef->section->vma);
  340.  
  341.               }
  342.           else {
  343.             result = new_rel(sdef->value + sdef->section->output_offset, os);
  344.           }
  345.         }
  346.           }
  347.         }
  348.         if (result.valid == false) {
  349.           einfo("%F%S: undefined symbol `%s' referenced in expression.\n",
  350.            tree->name.name);
  351.         }
  352.  
  353.       }
  354.     }
  355.  
  356.     break;
  357.  
  358.       case ADDR:
  359.  
  360.     if (allocation_done != lang_first_phase_enum) {
  361.       lang_output_section_statement_type *os =
  362.         lang_output_section_find(tree->name.name);
  363.       check(os,tree->name.name,"ADDR");
  364.       result =    new_rel((bfd_vma)0,  os);
  365.     }
  366.     else {
  367.       result = invalid();
  368.     }
  369.     break;
  370.       case SIZEOF:
  371.     if(allocation_done != lang_first_phase_enum) {
  372.       lang_output_section_statement_type *os = 
  373.         lang_output_section_find(tree->name.name);
  374.       check(os,tree->name.name,"SIZEOF");
  375.       result = new_abs((bfd_vma)(os->bfd_section->_raw_size));
  376.     }
  377.     else {
  378.       result = invalid();
  379.     }
  380.     break;
  381.  
  382.       default:
  383.     FAIL();
  384.     break;
  385.       }
  386.  
  387.   return result;
  388. }
  389. etree_value_type 
  390. DEFUN(exp_fold_tree,(tree, current_section, allocation_done,
  391.             dot, dotp),
  392.       etree_type *tree AND
  393.       lang_output_section_statement_type *current_section AND
  394.       lang_phase_type  allocation_done AND
  395.       bfd_vma dot AND
  396.       bfd_vma *dotp)
  397. {
  398.   etree_value_type result;
  399.  
  400.   if (tree == (etree_type *)NULL) {
  401.     result.valid = false;
  402.   }
  403.   else {
  404.     switch (tree->type.node_class) 
  405.     {
  406.      case etree_value:
  407.       result = new_rel(tree->value.value, current_section);
  408.       break;
  409.      case etree_unary:
  410.       result = exp_fold_tree(tree->unary.child,
  411.                  current_section,
  412.                  allocation_done, dot, dotp);
  413.       if (result.valid == true)
  414.       {
  415.     switch(tree->type.node_code) 
  416.     {
  417.      case ALIGN_K:
  418.       if (allocation_done != lang_first_phase_enum) {
  419.         result = new_rel_from_section(ALIGN_N(dot,
  420.                         result.value) ,
  421.                       current_section);
  422.  
  423.       }
  424.       else {
  425.         result.valid = false;
  426.       }
  427.       break;
  428.      case ABSOLUTE:
  429.       if (allocation_done != lang_first_phase_enum) 
  430.       {
  431.         if (current_section 
  432.         == (lang_output_section_statement_type*)NULL) 
  433.         {
  434.           /* Outside a section, so it's all ok */
  435.  
  436.         }
  437.         else {
  438.           /* Inside a section, subtract the base of the section,
  439.          so when it's added again (in an assignment), everything comes out fine
  440.          */
  441.           result.section = abs_output_section;
  442.           result.value -= current_section->bfd_section->vma;
  443.           result.valid = 1;
  444.         }
  445.       }
  446.       else 
  447.       {
  448.         result.valid = false;
  449.       }
  450.  
  451.       break;
  452.      case '~':
  453.       make_abs(&result);
  454.       result.value = ~result.value;
  455.       break;
  456.      case '!':
  457.       make_abs(&result);
  458.       result.value = !result.value;
  459.       break;
  460.      case '-':
  461.       make_abs(&result);
  462.       result.value = -result.value;
  463.       break;
  464.      case NEXT:
  465.       if (allocation_done ==lang_allocating_phase_enum) {
  466.         make_abs(&result);
  467.         result.value = ALIGN_N(dot, result.value);
  468.       }
  469.       else {
  470.         /* Return next place aligned to value */
  471.         result.valid = false;
  472.       }
  473.       break;
  474.      default:
  475.       FAIL();
  476.     }
  477.       }
  478.  
  479.       break;
  480.      case etree_trinary:
  481.  
  482.       result = exp_fold_tree(tree->trinary.cond,
  483.                  current_section,
  484.                  allocation_done, dot, dotp);
  485.       if (result.valid) {
  486.     result = exp_fold_tree(result.value ?
  487.                    tree->trinary.lhs:tree->trinary.rhs,
  488.                    current_section,
  489.                    allocation_done, dot, dotp);
  490.       }
  491.  
  492.       break;
  493.      case etree_binary:
  494.       result = fold_binary(tree, current_section, allocation_done,
  495.                dot, dotp);
  496.       break;
  497.      case etree_assign:
  498.       if (tree->assign.dst[0] == '.' && tree->assign.dst[1] == 0) {
  499.     /* Assignment to dot can only be done during allocation */
  500.     if (allocation_done == lang_allocating_phase_enum) {
  501.       result = exp_fold_tree(tree->assign.src,
  502.                  current_section,
  503.                  lang_allocating_phase_enum, dot, dotp);
  504.       if (result.valid == false) {
  505.         einfo("%F%S invalid assignment to location counter\n");
  506.       }
  507.       else {
  508.         if (current_section ==
  509.         (lang_output_section_statement_type  *)NULL) {
  510.           einfo("%F%S assignment to location counter invalid outside of SECTION\n");
  511.         }
  512.         else {
  513.           bfd_vma nextdot =result.value +
  514.            current_section->bfd_section->vma;
  515.           if (nextdot < dot) {
  516.         einfo("%F%S cannot move location counter backwards (from %V to %V)\n", dot, nextdot);
  517.           }
  518.           else {
  519.         *dotp = nextdot; 
  520.           }
  521.         }
  522.       }
  523.     }
  524.       }
  525.       else {
  526.     ldsym_type *sy = ldsym_get(tree->assign.dst);
  527.  
  528.     /* If this symbol has just been created then we'll place it into 
  529.      * a section of our choice
  530.      */
  531.     result = exp_fold_tree(tree->assign.src,
  532.                    current_section, allocation_done,
  533.                    dot, dotp);
  534.     if (result.valid)
  535.     {
  536.       asymbol *def;
  537.       asymbol **def_ptr ;
  538.       /* Add this definition to script file */
  539.       if (sy->sdefs_chain) 
  540.       {
  541.         def_ptr = sy->sdefs_chain;
  542.         def = *def_ptr;
  543.             
  544.       }
  545.       else 
  546.       {
  547.         def_ptr = (asymbol **)stat_alloc((bfd_size_type)(sizeof(asymbol **)));
  548.         def = (asymbol   *)bfd_make_empty_symbol(script_file->the_bfd);
  549.  
  550.           
  551.         def->flags = 0;
  552.         
  553.         sy->sdefs_chain = def_ptr;
  554.         *def_ptr = def;
  555.       }
  556.  
  557.       def->value = result.value;
  558.  
  559.       def->section = result.section->bfd_section;
  560.       def->flags = BSF_GLOBAL | BSF_EXPORT;
  561.  
  562.  
  563.       def->udata = (PTR)NULL;
  564.       def->name = sy->name;
  565.  
  566.       if (sy->sdefs_chain == 0)
  567.        Q_enter_global_ref(def_ptr, sy->name);
  568.     }
  569.  
  570.       }
  571.  
  572.   
  573.       break;
  574.      case etree_name:
  575.       result = fold_name(tree, current_section, allocation_done, dot);
  576.       break;
  577.      default:
  578.       einfo("%F%S Need more of these %d",tree->type.node_class );
  579.  
  580.     }
  581.   }
  582.  
  583.   return result;
  584. }
  585.  
  586.  
  587. etree_value_type 
  588. DEFUN(exp_fold_tree_no_dot,(tree, current_section, allocation_done),
  589.       etree_type *tree AND
  590.       lang_output_section_statement_type *current_section AND
  591.       lang_phase_type  allocation_done)
  592. {
  593. return exp_fold_tree(tree, current_section, allocation_done, (bfd_vma)
  594.              0, (bfd_vma *)NULL);
  595. }
  596.  
  597. etree_type *
  598. DEFUN(exp_binop,(code, lhs, rhs),
  599.       int code AND
  600.       etree_type *lhs AND
  601.       etree_type *rhs)
  602. {
  603.   etree_type value, *new;
  604.   etree_value_type r;
  605.  
  606.   value.type.node_code = code;
  607.   value.binary.lhs = lhs;
  608.   value.binary.rhs = rhs;
  609.   value.type.node_class = etree_binary;
  610.   r = exp_fold_tree_no_dot(&value,
  611.                abs_output_section,
  612.                lang_first_phase_enum );
  613.   if (r.valid)
  614.     {
  615.       return exp_intop(r.value);
  616.     }
  617.   new = (etree_type *)stat_alloc((bfd_size_type)(sizeof(new->binary)));
  618.   memcpy((char *)new, (char *)&value, sizeof(new->binary));
  619.   return new;
  620. }
  621.  
  622. etree_type *
  623. DEFUN(exp_trinop,(code, cond, lhs, rhs),
  624.       int code AND
  625.       etree_type *cond AND
  626.       etree_type *lhs AND
  627.       etree_type *rhs)
  628. {
  629.   etree_type value, *new;
  630.   etree_value_type r;
  631.   value.type.node_code = code;
  632.   value.trinary.lhs = lhs;
  633.   value.trinary.cond = cond;
  634.   value.trinary.rhs = rhs;
  635.   value.type.node_class = etree_trinary;
  636.   r= exp_fold_tree_no_dot(&value,  (lang_output_section_statement_type
  637.                     *)NULL,lang_first_phase_enum);
  638.   if (r.valid) {
  639.     return exp_intop(r.value);
  640.   }
  641.   new = (etree_type *)stat_alloc((bfd_size_type)(sizeof(new->trinary)));
  642.   memcpy((char *)new,(char *) &value, sizeof(new->trinary));
  643.   return new;
  644. }
  645.  
  646.  
  647. etree_type *
  648. DEFUN(exp_unop,(code, child),
  649.       int code AND
  650.       etree_type *child)
  651. {
  652.   etree_type value, *new;
  653.  
  654.   etree_value_type r;
  655.   value.unary.type.node_code = code;
  656.   value.unary.child = child;
  657.   value.unary.type.node_class = etree_unary;
  658.   r = exp_fold_tree_no_dot(&value,abs_output_section,
  659.                lang_first_phase_enum);
  660.   if (r.valid) {
  661.     return exp_intop(r.value);
  662.   }
  663.   new = (etree_type *)stat_alloc((bfd_size_type)(sizeof(new->unary)));
  664.   memcpy((char *)new, (char *)&value, sizeof(new->unary));
  665.   return new;
  666. }
  667.  
  668.  
  669. etree_type *
  670. DEFUN(exp_nameop,(code, name),
  671.       int code AND
  672.       CONST char *name)
  673. {
  674.  
  675.   etree_type value, *new;
  676.   etree_value_type r;
  677.   value.name.type.node_code = code;
  678.   value.name.name = name;
  679.   value.name.type.node_class = etree_name;
  680.  
  681.  
  682.   r = exp_fold_tree_no_dot(&value,
  683.                (lang_output_section_statement_type *)NULL,
  684.                lang_first_phase_enum);
  685.   if (r.valid) {
  686.     return exp_intop(r.value);
  687.   }
  688.   new = (etree_type *)stat_alloc((bfd_size_type)(sizeof(new->name)));
  689.   memcpy((char *)new, (char *)&value, sizeof(new->name));
  690.   return new;
  691.  
  692. }
  693.  
  694.  
  695.  
  696.  
  697. etree_type *
  698. DEFUN(exp_assop,(code, dst, src),
  699.       int code AND
  700.       CONST char *dst AND
  701.       etree_type *src)
  702. {
  703.   etree_type value, *new;
  704.  
  705.   value.assign.type.node_code = code;
  706.  
  707.  
  708.   value.assign.src = src;
  709.   value.assign.dst = dst;
  710.   value.assign.type.node_class = etree_assign;
  711.  
  712. #if 0
  713.   if (exp_fold_tree_no_dot(&value, &result)) {
  714.     return exp_intop(result);
  715.   }
  716. #endif
  717.   new = (etree_type*)stat_alloc((bfd_size_type)(sizeof(new->assign)));
  718.   memcpy((char *)new, (char *)&value, sizeof(new->assign));
  719.   return new;
  720. }
  721.  
  722. void 
  723. DEFUN(exp_print_tree,(tree),
  724.       etree_type *tree)
  725. {
  726.   switch (tree->type.node_class) {
  727.   case etree_value:
  728.     print_address(tree->value.value);
  729.     return;
  730.  
  731.   case etree_assign:
  732. #if 0
  733.     if (tree->assign.dst->sdefs != (asymbol *)NULL){
  734.       fprintf(config.map_file,"%s (%x) ",tree->assign.dst->name,
  735.           tree->assign.dst->sdefs->value);
  736.     }
  737.     else {
  738.       fprintf(config.map_file,"%s (UNDEFINED)",tree->assign.dst->name);
  739.     }
  740. #endif
  741.     fprintf(config.map_file,"%s ",tree->assign.dst);
  742.     exp_print_token(tree->type.node_code);
  743.     exp_print_tree(tree->assign.src);
  744.     break;
  745.   case etree_binary:
  746.     fprintf(config.map_file,"(");
  747.     exp_print_tree(tree->binary.lhs);
  748.     exp_print_token(tree->type.node_code);
  749.     exp_print_tree(tree->binary.rhs);
  750.     fprintf(config.map_file,")");
  751.     break;
  752.   case etree_trinary:
  753.     exp_print_tree(tree->trinary.cond);
  754.     fprintf(config.map_file,"?");
  755.     exp_print_tree(tree->trinary.lhs);
  756.     fprintf(config.map_file,":");
  757.     exp_print_tree(tree->trinary.rhs);
  758.     break;
  759.   case etree_unary:
  760.     exp_print_token(tree->unary.type.node_code);
  761.     if (tree->unary.child) 
  762.     {
  763.       
  764.     fprintf(config.map_file,"(");
  765.     exp_print_tree(tree->unary.child);
  766.     fprintf(config.map_file,")");
  767.   }
  768.     
  769.     break;
  770.   case etree_undef:
  771.     fprintf(config.map_file,"????????");
  772.     break;
  773.   case etree_name:
  774.     if (tree->type.node_code == NAME) {
  775.       fprintf(config.map_file,"%s", tree->name.name);
  776.     }
  777.     else {
  778.       exp_print_token(tree->type.node_code);
  779.       if (tree->name.name)
  780.       fprintf(config.map_file,"(%s)", tree->name.name);
  781.     }
  782.     break;
  783.   default:
  784.     FAIL();
  785.     break;
  786.   }
  787. }
  788.  
  789.  
  790.  
  791.  
  792. bfd_vma
  793. DEFUN(exp_get_vma,(tree, def, name, allocation_done),
  794.       etree_type *tree AND
  795.       bfd_vma def AND
  796.       char *name AND
  797.       lang_phase_type allocation_done)
  798. {
  799.   etree_value_type r;
  800.  
  801.   if (tree != (etree_type *)NULL) {
  802.     r = exp_fold_tree_no_dot(tree,
  803.          abs_output_section,
  804.               allocation_done);
  805.     if (r.valid == false && name) {
  806.       einfo("%F%S Nonconstant expression for %s\n",name);
  807.     }
  808.     return r.value;
  809.   }
  810.   else {
  811.     return def;
  812.   }
  813. }
  814.  
  815. int 
  816. DEFUN(exp_get_value_int,(tree,def,name, allocation_done),
  817.       etree_type *tree AND
  818.       int def AND
  819.       char *name AND
  820.       lang_phase_type allocation_done)
  821. {
  822.   return (int)exp_get_vma(tree,(bfd_vma)def,name, allocation_done);
  823. }
  824.  
  825.