// script.cc -- handle linker scripts for gold.

// Copyright 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
// Written by Ian Lance Taylor <iant@google.com>.

// This file is part of gold.

// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 3 of the License, or
// (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
// MA 02110-1301, USA.

#include "gold.h"

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <fnmatch.h>
#include <string>
#include <vector>
#include "filenames.h"

#include "elfcpp.h"
#include "demangle.h"
#include "dirsearch.h"
#include "options.h"
#include "fileread.h"
#include "workqueue.h"
#include "readsyms.h"
#include "parameters.h"
#include "layout.h"
#include "symtab.h"
#include "target-select.h"
#include "script.h"
#include "script-c.h"
#include "incremental.h"

namespace gold
{

// A token read from a script file.  We don't implement keywords here;
// all keywords are simply represented as a string.

class Token
{
 public:
  // Token classification.
  enum Classification
  {
    // Token is invalid.
    TOKEN_INVALID,
    // Token indicates end of input.
    TOKEN_EOF,
    // Token is a string of characters.
    TOKEN_STRING,
    // Token is a quoted string of characters.
    TOKEN_QUOTED_STRING,
    // Token is an operator.
    TOKEN_OPERATOR,
    // Token is a number (an integer).
    TOKEN_INTEGER
  };

  // We need an empty constructor so that we can put this STL objects.
  Token()
    : classification_(TOKEN_INVALID), value_(NULL), value_length_(0),
      opcode_(0), lineno_(0), charpos_(0)
  { }

  // A general token with no value.
  Token(Classification classification, int lineno, int charpos)
    : classification_(classification), value_(NULL), value_length_(0),
      opcode_(0), lineno_(lineno), charpos_(charpos)
  {
    gold_assert(classification == TOKEN_INVALID
		|| classification == TOKEN_EOF);
  }

  // A general token with a value.
  Token(Classification classification, const char* value, size_t length,
	int lineno, int charpos)
    : classification_(classification), value_(value), value_length_(length),
      opcode_(0), lineno_(lineno), charpos_(charpos)
  {
    gold_assert(classification != TOKEN_INVALID
		&& classification != TOKEN_EOF);
  }

  // A token representing an operator.
  Token(int opcode, int lineno, int charpos)
    : classification_(TOKEN_OPERATOR), value_(NULL), value_length_(0),
      opcode_(opcode), lineno_(lineno), charpos_(charpos)
  { }

  // Return whether the token is invalid.
  bool
  is_invalid() const
  { return this->classification_ == TOKEN_INVALID; }

  // Return whether this is an EOF token.
  bool
  is_eof() const
  { return this->classification_ == TOKEN_EOF; }

  // Return the token classification.
  Classification
  classification() const
  { return this->classification_; }

  // Return the line number at which the token starts.
  int
  lineno() const
  { return this->lineno_; }

  // Return the character position at this the token starts.
  int
  charpos() const
  { return this->charpos_; }

  // Get the value of a token.

  const char*
  string_value(size_t* length) const
  {
    gold_assert(this->classification_ == TOKEN_STRING
		|| this->classification_ == TOKEN_QUOTED_STRING);
    *length = this->value_length_;
    return this->value_;
  }

  int
  operator_value() const
  {
    gold_assert(this->classification_ == TOKEN_OPERATOR);
    return this->opcode_;
  }

  uint64_t
  integer_value() const
  {
    gold_assert(this->classification_ == TOKEN_INTEGER);
    // Null terminate.
    std::string s(this->value_, this->value_length_);
    return strtoull(s.c_str(), NULL, 0);
  }

 private:
  // The token classification.
  Classification classification_;
  // The token value, for TOKEN_STRING or TOKEN_QUOTED_STRING or
  // TOKEN_INTEGER.
  const char* value_;
  // The length of the token value.
  size_t value_length_;
  // The token value, for TOKEN_OPERATOR.
  int opcode_;
  // The line number where this token started (one based).
  int lineno_;
  // The character position within the line where this token started
  // (one based).
  int charpos_;
};

// This class handles lexing a file into a sequence of tokens.

class Lex
{
 public:
  // We unfortunately have to support different lexing modes, because
  // when reading different parts of a linker script we need to parse
  // things differently.
  enum Mode
  {
    // Reading an ordinary linker script.
    LINKER_SCRIPT,
    // Reading an expression in a linker script.
    EXPRESSION,
    // Reading a version script.
    VERSION_SCRIPT,
    // Reading a --dynamic-list file.
    DYNAMIC_LIST
  };

  Lex(const char* input_string, size_t input_length, int parsing_token)
    : input_string_(input_string), input_length_(input_length),
      current_(input_string), mode_(LINKER_SCRIPT),
      first_token_(parsing_token), token_(),
      lineno_(1), linestart_(input_string)
  { }

  // Read a file into a string.
  static void
  read_file(Input_file*, std::string*);

  // Return the next token.
  const Token*
  next_token();

  // Return the current lexing mode.
  Lex::Mode
  mode() const
  { return this->mode_; }

  // Set the lexing mode.
  void
  set_mode(Mode mode)
  { this->mode_ = mode; }

 private:
  Lex(const Lex&);
  Lex& operator=(const Lex&);

  // Make a general token with no value at the current location.
  Token
  make_token(Token::Classification c, const char* start) const
  { return Token(c, this->lineno_, start - this->linestart_ + 1); }

  // Make a general token with a value at the current location.
  Token
  make_token(Token::Classification c, const char* v, size_t len,
	     const char* start)
    const
  { return Token(c, v, len, this->lineno_, start - this->linestart_ + 1); }

  // Make an operator token at the current location.
  Token
  make_token(int opcode, const char* start) const
  { return Token(opcode, this->lineno_, start - this->linestart_ + 1); }

  // Make an invalid token at the current location.
  Token
  make_invalid_token(const char* start)
  { return this->make_token(Token::TOKEN_INVALID, start); }

  // Make an EOF token at the current location.
  Token
  make_eof_token(const char* start)
  { return this->make_token(Token::TOKEN_EOF, start); }

  // Return whether C can be the first character in a name.  C2 is the
  // next character, since we sometimes need that.
  inline bool
  can_start_name(char c, char c2);

  // If C can appear in a name which has already started, return a
  // pointer to a character later in the token or just past
  // it. Otherwise, return NULL.
  inline const char*
  can_continue_name(const char* c);

  // Return whether C, C2, C3 can start a hex number.
  inline bool
  can_start_hex(char c, char c2, char c3);

  // If C can appear in a hex number which has already started, return
  // a pointer to a character later in the token or just past
  // it. Otherwise, return NULL.
  inline const char*
  can_continue_hex(const char* c);

  // Return whether C can start a non-hex number.
  static inline bool
  can_start_number(char c);

  // If C can appear in a decimal number which has already started,
  // return a pointer to a character later in the token or just past
  // it. Otherwise, return NULL.
  inline const char*
  can_continue_number(const char* c)
  { return Lex::can_start_number(*c) ? c + 1 : NULL; }

  // If C1 C2 C3 form a valid three character operator, return the
  // opcode.  Otherwise return 0.
  static inline int
  three_char_operator(char c1, char c2, char c3);

  // If C1 C2 form a valid two character operator, return the opcode.
  // Otherwise return 0.
  static inline int
  two_char_operator(char c1, char c2);

  // If C1 is a valid one character operator, return the opcode.
  // Otherwise return 0.
  static inline int
  one_char_operator(char c1);

  // Read the next token.
  Token
  get_token(const char**);

  // Skip a C style /* */ comment.  Return false if the comment did
  // not end.
  bool
  skip_c_comment(const char**);

  // Skip a line # comment.  Return false if there was no newline.
  bool
  skip_line_comment(const char**);

  // Build a token CLASSIFICATION from all characters that match
  // CAN_CONTINUE_FN.  The token starts at START.  Start matching from
  // MATCH.  Set *PP to the character following the token.
  inline Token
  gather_token(Token::Classification,
	       const char* (Lex::*can_continue_fn)(const char*),
	       const char* start, const char* match, const char** pp);

  // Build a token from a quoted string.
  Token
  gather_quoted_string(const char** pp);

  // The string we are tokenizing.
  const char* input_string_;
  // The length of the string.
  size_t input_length_;
  // The current offset into the string.
  const char* current_;
  // The current lexing mode.
  Mode mode_;
  // The code to use for the first token.  This is set to 0 after it
  // is used.
  int first_token_;
  // The current token.
  Token token_;
  // The current line number.
  int lineno_;
  // The start of the current line in the string.
  const char* linestart_;
};

// Read the whole file into memory.  We don't expect linker scripts to
// be large, so we just use a std::string as a buffer.  We ignore the
// data we've already read, so that we read aligned buffers.

void
Lex::read_file(Input_file* input_file, std::string* contents)
{
  off_t filesize = input_file->file().filesize();
  contents->clear();
  contents->reserve(filesize);

  off_t off = 0;
  unsigned char buf[BUFSIZ];
  while (off < filesize)
    {
      off_t get = BUFSIZ;
      if (get > filesize - off)
	get = filesize - off;
      input_file->file().read(off, get, buf);
      contents->append(reinterpret_cast<char*>(&buf[0]), get);
      off += get;
    }
}

// Return whether C can be the start of a name, if the next character
// is C2.  A name can being with a letter, underscore, period, or
// dollar sign.  Because a name can be a file name, we also permit
// forward slash, backslash, and tilde.  Tilde is the tricky case
// here; GNU ld also uses it as a bitwise not operator.  It is only
// recognized as the operator if it is not immediately followed by
// some character which can appear in a symbol.  That is, when we
// don't know that we are looking at an expression, "~0" is a file
// name, and "~ 0" is an expression using bitwise not.  We are
// compatible.

inline bool
Lex::can_start_name(char c, char c2)
{
  switch (c)
    {
    case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
    case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
    case 'M': case 'N': case 'O': case 'Q': case 'P': case 'R':
    case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
    case 'Y': case 'Z':
    case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
    case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
    case 'm': case 'n': case 'o': case 'q': case 'p': case 'r':
    case 's': case 't': case 'u': case 'v': case 'w': case 'x':
    case 'y': case 'z':
    case '_': case '.': case '$':
      return true;

    case '/': case '\\':
      return this->mode_ == LINKER_SCRIPT;

    case '~':
      return this->mode_ == LINKER_SCRIPT && can_continue_name(&c2);

    case '*': case '[':
      return (this->mode_ == VERSION_SCRIPT
              || this->mode_ == DYNAMIC_LIST
	      || (this->mode_ == LINKER_SCRIPT
		  && can_continue_name(&c2)));

    default:
      return false;
    }
}

// Return whether C can continue a name which has already started.
// Subsequent characters in a name are the same as the leading
// characters, plus digits and "=+-:[],?*".  So in general the linker
// script language requires spaces around operators, unless we know
// that we are parsing an expression.

inline const char*
Lex::can_continue_name(const char* c)
{
  switch (*c)
    {
    case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
    case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
    case 'M': case 'N': case 'O': case 'Q': case 'P': case 'R':
    case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
    case 'Y': case 'Z':
    case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
    case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
    case 'm': case 'n': case 'o': case 'q': case 'p': case 'r':
    case 's': case 't': case 'u': case 'v': case 'w': case 'x':
    case 'y': case 'z':
    case '_': case '.': case '$':
    case '0': case '1': case '2': case '3': case '4':
    case '5': case '6': case '7': case '8': case '9':
      return c + 1;

    // TODO(csilvers): why not allow ~ in names for version-scripts?
    case '/': case '\\': case '~':
    case '=': case '+':
    case ',':
      if (this->mode_ == LINKER_SCRIPT)
        return c + 1;
      return NULL;

    case '[': case ']': case '*': case '?': case '-':
      if (this->mode_ == LINKER_SCRIPT || this->mode_ == VERSION_SCRIPT
          || this->mode_ == DYNAMIC_LIST)
        return c + 1;
      return NULL;

    // TODO(csilvers): why allow this?  ^ is meaningless in version scripts.
    case '^':
      if (this->mode_ == VERSION_SCRIPT || this->mode_ == DYNAMIC_LIST)
        return c + 1;
      return NULL;

    case ':':
      if (this->mode_ == LINKER_SCRIPT)
        return c + 1;
      else if ((this->mode_ == VERSION_SCRIPT || this->mode_ == DYNAMIC_LIST)
               && (c[1] == ':'))
        {
          // A name can have '::' in it, as that's a c++ namespace
          // separator. But a single colon is not part of a name.
          return c + 2;
        }
      return NULL;

    default:
      return NULL;
    }
}

// For a number we accept 0x followed by hex digits, or any sequence
// of digits.  The old linker accepts leading '$' for hex, and
// trailing HXBOD.  Those are for MRI compatibility and we don't
// accept them.  The old linker also accepts trailing MK for mega or
// kilo.  FIXME: Those are mentioned in the documentation, and we
// should accept them.

// Return whether C1 C2 C3 can start a hex number.

inline bool
Lex::can_start_hex(char c1, char c2, char c3)
{
  if (c1 == '0' && (c2 == 'x' || c2 == 'X'))
    return this->can_continue_hex(&c3);
  return false;
}

// Return whether C can appear in a hex number.

inline const char*
Lex::can_continue_hex(const char* c)
{
  switch (*c)
    {
    case '0': case '1': case '2': case '3': case '4':
    case '5': case '6': case '7': case '8': case '9':
    case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
    case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
      return c + 1;

    default:
      return NULL;
    }
}

// Return whether C can start a non-hex number.

inline bool
Lex::can_start_number(char c)
{
  switch (c)
    {
    case '0': case '1': case '2': case '3': case '4':
    case '5': case '6': case '7': case '8': case '9':
      return true;

    default:
      return false;
    }
}

// If C1 C2 C3 form a valid three character operator, return the
// opcode (defined in the yyscript.h file generated from yyscript.y).
// Otherwise return 0.

inline int
Lex::three_char_operator(char c1, char c2, char c3)
{
  switch (c1)
    {
    case '<':
      if (c2 == '<' && c3 == '=')
	return LSHIFTEQ;
      break;
    case '>':
      if (c2 == '>' && c3 == '=')
	return RSHIFTEQ;
      break;
    default:
      break;
    }
  return 0;
}

// If C1 C2 form a valid two character operator, return the opcode
// (defined in the yyscript.h file generated from yyscript.y).
// Otherwise return 0.

inline int
Lex::two_char_operator(char c1, char c2)
{
  switch (c1)
    {
    case '=':
      if (c2 == '=')
	return EQ;
      break;
    case '!':
      if (c2 == '=')
	return NE;
      break;
    case '+':
      if (c2 == '=')
	return PLUSEQ;
      break;
    case '-':
      if (c2 == '=')
	return MINUSEQ;
      break;
    case '*':
      if (c2 == '=')
	return MULTEQ;
      break;
    case '/':
      if (c2 == '=')
	return DIVEQ;
      break;
    case '|':
      if (c2 == '=')
	return OREQ;
      if (c2 == '|')
	return OROR;
      break;
    case '&':
      if (c2 == '=')
	return ANDEQ;
      if (c2 == '&')
	return ANDAND;
      break;
    case '>':
      if (c2 == '=')
	return GE;
      if (c2 == '>')
	return RSHIFT;
      break;
    case '<':
      if (c2 == '=')
	return LE;
      if (c2 == '<')
	return LSHIFT;
      break;
    default:
      break;
    }
  return 0;
}

// If C1 is a valid operator, return the opcode.  Otherwise return 0.

inline int
Lex::one_char_operator(char c1)
{
  switch (c1)
    {
    case '+':
    case '-':
    case '*':
    case '/':
    case '%':
    case '!':
    case '&':
    case '|':
    case '^':
    case '~':
    case '<':
    case '>':
    case '=':
    case '?':
    case ',':
    case '(':
    case ')':
    case '{':
    case '}':
    case '[':
    case ']':
    case ':':
    case ';':
      return c1;
    default:
      return 0;
    }
}

// Skip a C style comment.  *PP points to just after the "/*".  Return
// false if the comment did not end.

bool
Lex::skip_c_comment(const char** pp)
{
  const char* p = *pp;
  while (p[0] != '*' || p[1] != '/')
    {
      if (*p == '\0')
	{
	  *pp = p;
	  return false;
	}

      if (*p == '\n')
	{
	  ++this->lineno_;
	  this->linestart_ = p + 1;
	}
      ++p;
    }

  *pp = p + 2;
  return true;
}

// Skip a line # comment.  Return false if there was no newline.

bool
Lex::skip_line_comment(const char** pp)
{
  const char* p = *pp;
  size_t skip = strcspn(p, "\n");
  if (p[skip] == '\0')
    {
      *pp = p + skip;
      return false;
    }

  p += skip + 1;
  ++this->lineno_;
  this->linestart_ = p;
  *pp = p;

  return true;
}

// Build a token CLASSIFICATION from all characters that match
// CAN_CONTINUE_FN.  Update *PP.

inline Token
Lex::gather_token(Token::Classification classification,
		  const char* (Lex::*can_continue_fn)(const char*),
		  const char* start,
		  const char* match,
		  const char** pp)
{
  const char* new_match = NULL;
  while ((new_match = (this->*can_continue_fn)(match)))
    match = new_match;
  *pp = match;
  return this->make_token(classification, start, match - start, start);
}

// Build a token from a quoted string.

Token
Lex::gather_quoted_string(const char** pp)
{
  const char* start = *pp;
  const char* p = start;
  ++p;
  size_t skip = strcspn(p, "\"\n");
  if (p[skip] != '"')
    return this->make_invalid_token(start);
  *pp = p + skip + 1;
  return this->make_token(Token::TOKEN_QUOTED_STRING, p, skip, start);
}

// Return the next token at *PP.  Update *PP.  General guideline: we
// require linker scripts to be simple ASCII.  No unicode linker
// scripts.  In particular we can assume that any '\0' is the end of
// the input.

Token
Lex::get_token(const char** pp)
{
  const char* p = *pp;

  while (true)
    {
      if (*p == '\0')
	{
	  *pp = p;
	  return this->make_eof_token(p);
	}

      // Skip whitespace quickly.
      while (*p == ' ' || *p == '\t' || *p == '\r')
	++p;

      if (*p == '\n')
	{
	  ++p;
	  ++this->lineno_;
	  this->linestart_ = p;
	  continue;
	}

      // Skip C style comments.
      if (p[0] == '/' && p[1] == '*')
	{
	  int lineno = this->lineno_;
	  int charpos = p - this->linestart_ + 1;

	  *pp = p + 2;
	  if (!this->skip_c_comment(pp))
	    return Token(Token::TOKEN_INVALID, lineno, charpos);
	  p = *pp;

	  continue;
	}

      // Skip line comments.
      if (*p == '#')
	{
	  *pp = p + 1;
	  if (!this->skip_line_comment(pp))
	    return this->make_eof_token(p);
	  p = *pp;
	  continue;
	}

      // Check for a name.
      if (this->can_start_name(p[0], p[1]))
	return this->gather_token(Token::TOKEN_STRING,
				  &Lex::can_continue_name,
				  p, p + 1, pp);

      // We accept any arbitrary name in double quotes, as long as it
      // does not cross a line boundary.
      if (*p == '"')
	{
	  *pp = p;
	  return this->gather_quoted_string(pp);
	}

      // Check for a number.

      if (this->can_start_hex(p[0], p[1], p[2]))
	return this->gather_token(Token::TOKEN_INTEGER,
				  &Lex::can_continue_hex,
				  p, p + 3, pp);

      if (Lex::can_start_number(p[0]))
	return this->gather_token(Token::TOKEN_INTEGER,
				  &Lex::can_continue_number,
				  p, p + 1, pp);

      // Check for operators.

      int opcode = Lex::three_char_operator(p[0], p[1], p[2]);
      if (opcode != 0)
	{
	  *pp = p + 3;
	  return this->make_token(opcode, p);
	}

      opcode = Lex::two_char_operator(p[0], p[1]);
      if (opcode != 0)
	{
	  *pp = p + 2;
	  return this->make_token(opcode, p);
	}

      opcode = Lex::one_char_operator(p[0]);
      if (opcode != 0)
	{
	  *pp = p + 1;
	  return this->make_token(opcode, p);
	}

      return this->make_token(Token::TOKEN_INVALID, p);
    }
}

// Return the next token.

const Token*
Lex::next_token()
{
  // The first token is special.
  if (this->first_token_ != 0)
    {
      this->token_ = Token(this->first_token_, 0, 0);
      this->first_token_ = 0;
      return &this->token_;
    }

  this->token_ = this->get_token(&this->current_);

  // Don't let an early null byte fool us into thinking that we've
  // reached the end of the file.
  if (this->token_.is_eof()
      && (static_cast<size_t>(this->current_ - this->input_string_)
	  < this->input_length_))
    this->token_ = this->make_invalid_token(this->current_);

  return &this->token_;
}

// class Symbol_assignment.

// Add the symbol to the symbol table.  This makes sure the symbol is
// there and defined.  The actual value is stored later.  We can't
// determine the actual value at this point, because we can't
// necessarily evaluate the expression until all ordinary symbols have
// been finalized.

// The GNU linker lets symbol assignments in the linker script
// silently override defined symbols in object files.  We are
// compatible.  FIXME: Should we issue a warning?

void
Symbol_assignment::add_to_table(Symbol_table* symtab)
{
  elfcpp::STV vis = this->hidden_ ? elfcpp::STV_HIDDEN : elfcpp::STV_DEFAULT;
  this->sym_ = symtab->define_as_constant(this->name_.c_str(),
					  NULL, // version
					  (this->is_defsym_
					   ? Symbol_table::DEFSYM
					   : Symbol_table::SCRIPT),
					  0, // value
					  0, // size
					  elfcpp::STT_NOTYPE,
					  elfcpp::STB_GLOBAL,
					  vis,
					  0, // nonvis
					  this->provide_,
                                          true); // force_override
}

// Finalize a symbol value.

void
Symbol_assignment::finalize(Symbol_table* symtab, const Layout* layout)
{
  this->finalize_maybe_dot(symtab, layout, false, 0, NULL);
}

// Finalize a symbol value which can refer to the dot symbol.

void
Symbol_assignment::finalize_with_dot(Symbol_table* symtab,
				     const Layout* layout,
				     uint64_t dot_value,
				     Output_section* dot_section)
{
  this->finalize_maybe_dot(symtab, layout, true, dot_value, dot_section);
}

// Finalize a symbol value, internal version.

void
Symbol_assignment::finalize_maybe_dot(Symbol_table* symtab,
				      const Layout* layout,
				      bool is_dot_available,
				      uint64_t dot_value,
				      Output_section* dot_section)
{
  // If we were only supposed to provide this symbol, the sym_ field
  // will be NULL if the symbol was not referenced.
  if (this->sym_ == NULL)
    {
      gold_assert(this->provide_);
      return;
    }

  if (parameters->target().get_size() == 32)
    {
#if defined(HAVE_TARGET_32_LITTLE) || defined(HAVE_TARGET_32_BIG)
      this->sized_finalize<32>(symtab, layout, is_dot_available, dot_value,
			       dot_section);
#else
      gold_unreachable();
#endif
    }
  else if (parameters->target().get_size() == 64)
    {
#if defined(HAVE_TARGET_64_LITTLE) || defined(HAVE_TARGET_64_BIG)
      this->sized_finalize<64>(symtab, layout, is_dot_available, dot_value,
			       dot_section);
#else
      gold_unreachable();
#endif
    }
  else
    gold_unreachable();
}

template<int size>
void
Symbol_assignment::sized_finalize(Symbol_table* symtab, const Layout* layout,
				  bool is_dot_available, uint64_t dot_value,
				  Output_section* dot_section)
{
  Output_section* section;
  uint64_t final_val = this->val_->eval_maybe_dot(symtab, layout, true,
						  is_dot_available,
						  dot_value, dot_section,
						  &section, NULL);
  Sized_symbol<size>* ssym = symtab->get_sized_symbol<size>(this->sym_);
  ssym->set_value(final_val);
  if (section != NULL)
    ssym->set_output_section(section);
}

// Set the symbol value if the expression yields an absolute value.

void
Symbol_assignment::set_if_absolute(Symbol_table* symtab, const Layout* layout,
				   bool is_dot_available, uint64_t dot_value)
{
  if (this->sym_ == NULL)
    return;

  Output_section* val_section;
  uint64_t val = this->val_->eval_maybe_dot(symtab, layout, false,
					    is_dot_available, dot_value,
					    NULL, &val_section, NULL);
  if (val_section != NULL)
    return;

  if (parameters->target().get_size() == 32)
    {
#if defined(HAVE_TARGET_32_LITTLE) || defined(HAVE_TARGET_32_BIG)
      Sized_symbol<32>* ssym = symtab->get_sized_symbol<32>(this->sym_);
      ssym->set_value(val);
#else
      gold_unreachable();
#endif
    }
  else if (parameters->target().get_size() == 64)
    {
#if defined(HAVE_TARGET_64_LITTLE) || defined(HAVE_TARGET_64_BIG)
      Sized_symbol<64>* ssym = symtab->get_sized_symbol<64>(this->sym_);
      ssym->set_value(val);
#else
      gold_unreachable();
#endif
    }
  else
    gold_unreachable();
}

// Print for debugging.

void
Symbol_assignment::print(FILE* f) const
{
  if (this->provide_ && this->hidden_)
    fprintf(f, "PROVIDE_HIDDEN(");
  else if (this->provide_)
    fprintf(f, "PROVIDE(");
  else if (this->hidden_)
    gold_unreachable();

  fprintf(f, "%s = ", this->name_.c_str());
  this->val_->print(f);

  if (this->provide_ || this->hidden_)
    fprintf(f, ")");

  fprintf(f, "\n");
}

// Class Script_assertion.

// Check the assertion.

void
Script_assertion::check(const Symbol_table* symtab, const Layout* layout)
{
  if (!this->check_->eval(symtab, layout, true))
    gold_error("%s", this->message_.c_str());
}

// Print for debugging.

void
Script_assertion::print(FILE* f) const
{
  fprintf(f, "ASSERT(");
  this->check_->print(f);
  fprintf(f, ", \"%s\")\n", this->message_.c_str());
}

// Class Script_options.

Script_options::Script_options()
  : entry_(), symbol_assignments_(), symbol_definitions_(),
    symbol_references_(), version_script_info_(), script_sections_()
{
}

// Returns true if NAME is on the list of symbol assignments waiting
// to be processed.

bool
Script_options::is_pending_assignment(const char* name)
{
  for (Symbol_assignments::iterator p = this->symbol_assignments_.begin();
       p != this->symbol_assignments_.end();
       ++p)
    if ((*p)->name() == name)
      return true;
  return false;
}

// Add a symbol to be defined.

void
Script_options::add_symbol_assignment(const char* name, size_t length,
				      bool is_defsym, Expression* value,
				      bool provide, bool hidden)
{
  if (length != 1 || name[0] != '.')
    {
      if (this->script_sections_.in_sections_clause())
	{
	  gold_assert(!is_defsym);
	  this->script_sections_.add_symbol_assignment(name, length, value,
						       provide, hidden);
	}
      else
	{
	  Symbol_assignment* p = new Symbol_assignment(name, length, is_defsym,
						       value, provide, hidden);
	  this->symbol_assignments_.push_back(p);
	}

      if (!provide)
	{
	  std::string n(name, length);
	  this->symbol_definitions_.insert(n);
	  this->symbol_references_.erase(n);
	}
    }
  else
    {
      if (provide || hidden)
	gold_error(_("invalid use of PROVIDE for dot symbol"));

      // The GNU linker permits assignments to dot outside of SECTIONS
      // clauses and treats them as occurring inside, so we don't
      // check in_sections_clause here.
      this->script_sections_.add_dot_assignment(value);
    }
}

// Add a reference to a symbol.

void
Script_options::add_symbol_reference(const char* name, size_t length)
{
  if (length != 1 || name[0] != '.')
    {
      std::string n(name, length);
      if (this->symbol_definitions_.find(n) == this->symbol_definitions_.end())
	this->symbol_references_.insert(n);
    }
}

// Add an assertion.

void
Script_options::add_assertion(Expression* check, const char* message,
			      size_t messagelen)
{
  if (this->script_sections_.in_sections_clause())
    this->script_sections_.add_assertion(check, message, messagelen);
  else
    {
      Script_assertion* p = new Script_assertion(check, message, messagelen);
      this->assertions_.push_back(p);
    }
}

// Create sections required by any linker scripts.

void
Script_options::create_script_sections(Layout* layout)
{
  if (this->saw_sections_clause())
    this->script_sections_.create_sections(layout);
}

// Add any symbols we are defining to the symbol table.

void
Script_options::add_symbols_to_table(Symbol_table* symtab)
{
  for (Symbol_assignments::iterator p = this->symbol_assignments_.begin();
       p != this->symbol_assignments_.end();
       ++p)
    (*p)->add_to_table(symtab);
  this->script_sections_.add_symbols_to_table(symtab);
}

// Finalize symbol values.  Also check assertions.

void
Script_options::finalize_symbols(Symbol_table* symtab, const Layout* layout)
{
  // We finalize the symbols defined in SECTIONS first, because they
  // are the ones which may have changed.  This way if symbol outside
  // SECTIONS are defined in terms of symbols inside SECTIONS, they
  // will get the right value.
  this->script_sections_.finalize_symbols(symtab, layout);

  for (Symbol_assignments::iterator p = this->symbol_assignments_.begin();
       p != this->symbol_assignments_.end();
       ++p)
    (*p)->finalize(symtab, layout);

  for (Assertions::iterator p = this->assertions_.begin();
       p != this->assertions_.end();
       ++p)
    (*p)->check(symtab, layout);
}

// Set section addresses.  We set all the symbols which have absolute
// values.  Then we let the SECTIONS clause do its thing.  This
// returns the segment which holds the file header and segment
// headers, if any.

Output_segment*
Script_options::set_section_addresses(Symbol_table* symtab, Layout* layout)
{
  for (Symbol_assignments::iterator p = this->symbol_assignments_.begin();
       p != this->symbol_assignments_.end();
       ++p)
    (*p)->set_if_absolute(symtab, layout, false, 0);

  return this->script_sections_.set_section_addresses(symtab, layout);
}

// This class holds data passed through the parser to the lexer and to
// the parser support functions.  This avoids global variables.  We
// can't use global variables because we need not be called by a
// singleton thread.

class Parser_closure
{
 public:
  Parser_closure(const char* filename,
		 const Position_dependent_options& posdep_options,
		 bool parsing_defsym, bool in_group, bool is_in_sysroot,
                 Command_line* command_line,
		 Script_options* script_options,
		 Lex* lex,
		 bool skip_on_incompatible_target)
    : filename_(filename), posdep_options_(posdep_options),
      parsing_defsym_(parsing_defsym), in_group_(in_group),
      is_in_sysroot_(is_in_sysroot),
      skip_on_incompatible_target_(skip_on_incompatible_target),
      found_incompatible_target_(false),
      command_line_(command_line), script_options_(script_options),
      version_script_info_(script_options->version_script_info()),
      lex_(lex), lineno_(0), charpos_(0), lex_mode_stack_(), inputs_(NULL)
  {
    // We start out processing C symbols in the default lex mode.
    this->language_stack_.push_back(Version_script_info::LANGUAGE_C);
    this->lex_mode_stack_.push_back(lex->mode());
  }

  // Return the file name.
  const char*
  filename() const
  { return this->filename_; }

  // Return the position dependent options.  The caller may modify
  // this.
  Position_dependent_options&
  position_dependent_options()
  { return this->posdep_options_; }

  // Whether we are parsing a --defsym.
  bool
  parsing_defsym() const
  { return this->parsing_defsym_; }

  // Return whether this script is being run in a group.
  bool
  in_group() const
  { return this->in_group_; }

  // Return whether this script was found using a directory in the
  // sysroot.
  bool
  is_in_sysroot() const
  { return this->is_in_sysroot_; }

  // Whether to skip to the next file with the same name if we find an
  // incompatible target in an OUTPUT_FORMAT statement.
  bool
  skip_on_incompatible_target() const
  { return this->skip_on_incompatible_target_; }

  // Stop skipping to the next file on an incompatible target.  This
  // is called when we make some unrevocable change to the data
  // structures.
  void
  clear_skip_on_incompatible_target()
  { this->skip_on_incompatible_target_ = false; }

  // Whether we found an incompatible target in an OUTPUT_FORMAT
  // statement.
  bool
  found_incompatible_target() const
  { return this->found_incompatible_target_; }

  // Note that we found an incompatible target.
  void
  set_found_incompatible_target()
  { this->found_incompatible_target_ = true; }

  // Returns the Command_line structure passed in at constructor time.
  // This value may be NULL.  The caller may modify this, which modifies
  // the passed-in Command_line object (not a copy).
  Command_line*
  command_line()
  { return this->command_line_; }

  // Return the options which may be set by a script.
  Script_options*
  script_options()
  { return this->script_options_; }

  // Return the object in which version script information should be stored.
  Version_script_info*
  version_script()
  { return this->version_script_info_; }

  // Return the next token, and advance.
  const Token*
  next_token()
  {
    const Token* token = this->lex_->next_token();
    this->lineno_ = token->lineno();
    this->charpos_ = token->charpos();
    return token;
  }

  // Set a new lexer mode, pushing the current one.
  void
  push_lex_mode(Lex::Mode mode)
  {
    this->lex_mode_stack_.push_back(this->lex_->mode());
    this->lex_->set_mode(mode);
  }

  // Pop the lexer mode.
  void
  pop_lex_mode()
  {
    gold_assert(!this->lex_mode_stack_.empty());
    this->lex_->set_mode(this->lex_mode_stack_.back());
    this->lex_mode_stack_.pop_back();
  }

  // Return the current lexer mode.
  Lex::Mode
  lex_mode() const
  { return this->lex_mode_stack_.back(); }

  // Return the line number of the last token.
  int
  lineno() const
  { return this->lineno_; }

  // Return the character position in the line of the last token.
  int
  charpos() const
  { return this->charpos_; }

  // Return the list of input files, creating it if necessary.  This
  // is a space leak--we never free the INPUTS_ pointer.
  Input_arguments*
  inputs()
  {
    if (this->inputs_ == NULL)
      this->inputs_ = new Input_arguments();
    return this->inputs_;
  }

  // Return whether we saw any input files.
  bool
  saw_inputs() const
  { return this->inputs_ != NULL && !this->inputs_->empty(); }

  // Return the current language being processed in a version script
  // (eg, "C++").  The empty string represents unmangled C names.
  Version_script_info::Language
  get_current_language() const
  { return this->language_stack_.back(); }

  // Push a language onto the stack when entering an extern block.
  void
  push_language(Version_script_info::Language lang)
  { this->language_stack_.push_back(lang); }

  // Pop a language off of the stack when exiting an extern block.
  void
  pop_language()
  {
    gold_assert(!this->language_stack_.empty());
    this->language_stack_.pop_back();
  }

 private:
  // The name of the file we are reading.
  const char* filename_;
  // The position dependent options.
  Position_dependent_options posdep_options_;
  // True if we are parsing a --defsym.
  bool parsing_defsym_;
  // Whether we are currently in a --start-group/--end-group.
  bool in_group_;
  // Whether the script was found in a sysrooted directory.
  bool is_in_sysroot_;
  // If this is true, then if we find an OUTPUT_FORMAT with an
  // incompatible target, then we tell the parser to abort so that we
  // can search for the next file with the same name.
  bool skip_on_incompatible_target_;
  // True if we found an OUTPUT_FORMAT with an incompatible target.
  bool found_incompatible_target_;
  // May be NULL if the user chooses not to pass one in.
  Command_line* command_line_;
  // Options which may be set from any linker script.
  Script_options* script_options_;
  // Information parsed from a version script.
  Version_script_info* version_script_info_;
  // The lexer.
  Lex* lex_;
  // The line number of the last token returned by next_token.
  int lineno_;
  // The column number of the last token returned by next_token.
  int charpos_;
  // A stack of lexer modes.
  std::vector<Lex::Mode> lex_mode_stack_;
  // A stack of which extern/language block we're inside. Can be C++,
  // java, or empty for C.
  std::vector<Version_script_info::Language> language_stack_;
  // New input files found to add to the link.
  Input_arguments* inputs_;
};

// FILE was found as an argument on the command line.  Try to read it
// as a script.  Return true if the file was handled.

bool
read_input_script(Workqueue* workqueue, Symbol_table* symtab, Layout* layout,
		  Dirsearch* dirsearch, int dirindex,
		  Input_objects* input_objects, Mapfile* mapfile,
		  Input_group* input_group,
		  const Input_argument* input_argument,
		  Input_file* input_file, Task_token* next_blocker,
		  bool* used_next_blocker)
{
  *used_next_blocker = false;

  std::string input_string;
  Lex::read_file(input_file, &input_string);

  Lex lex(input_string.c_str(), input_string.length(), PARSING_LINKER_SCRIPT);

  Parser_closure closure(input_file->filename().c_str(),
			 input_argument->file().options(),
			 false,
			 input_group != NULL,
			 input_file->is_in_sysroot(),
                         NULL,
			 layout->script_options(),
			 &lex,
			 input_file->will_search_for());

  bool old_saw_sections_clause =
    layout->script_options()->saw_sections_clause();

  if (yyparse(&closure) != 0)
    {
      if (closure.found_incompatible_target())
	{
	  Read_symbols::incompatible_warning(input_argument, input_file);
	  Read_symbols::requeue(workqueue, input_objects, symtab, layout,
				dirsearch, dirindex, mapfile, input_argument,
				input_group, next_blocker);
	  return true;
	}
      return false;
    }

  if (!old_saw_sections_clause
      && layout->script_options()->saw_sections_clause()
      && layout->have_added_input_section())
    gold_error(_("%s: SECTIONS seen after other input files; try -T/--script"),
	       input_file->filename().c_str());

  if (!closure.saw_inputs())
    return true;

  Task_token* this_blocker = NULL;
  for (Input_arguments::const_iterator p = closure.inputs()->begin();
       p != closure.inputs()->end();
       ++p)
    {
      Task_token* nb;
      if (p + 1 == closure.inputs()->end())
	nb = next_blocker;
      else
	{
	  nb = new Task_token(true);
	  nb->add_blocker();
	}
      workqueue->queue_soon(new Read_symbols(input_objects, symtab,
					     layout, dirsearch, 0, mapfile, &*p,
					     input_group, NULL, this_blocker, nb));
      this_blocker = nb;
    }

  if (layout->incremental_inputs() != NULL)
    {
      // Like new Read_symbols(...) above, we rely on closure.inputs()
      // getting leaked by closure.
      const std::string& filename = input_file->filename();
      Script_info* info = new Script_info(closure.inputs());
      Timespec mtime = input_file->file().get_mtime();
      layout->incremental_inputs()->report_script(filename, info, mtime);
    }

  *used_next_blocker = true;

  return true;
}

// Helper function for read_version_script() and
// read_commandline_script().  Processes the given file in the mode
// indicated by first_token and lex_mode.

static bool
read_script_file(const char* filename, Command_line* cmdline,
                 Script_options* script_options,
                 int first_token, Lex::Mode lex_mode)
{
  // TODO: if filename is a relative filename, search for it manually
  // using "." + cmdline->options()->search_path() -- not dirsearch.
  Dirsearch dirsearch;

  // The file locking code wants to record a Task, but we haven't
  // started the workqueue yet.  This is only for debugging purposes,
  // so we invent a fake value.
  const Task* task = reinterpret_cast<const Task*>(-1);

  // We don't want this file to be opened in binary mode.
  Position_dependent_options posdep = cmdline->position_dependent_options();
  if (posdep.format_enum() == General_options::OBJECT_FORMAT_BINARY)
    posdep.set_format_enum(General_options::OBJECT_FORMAT_ELF);
  Input_file_argument input_argument(filename,
				     Input_file_argument::INPUT_FILE_TYPE_FILE,
				     "", false, posdep);
  Input_file input_file(&input_argument);
  int dummy = 0;
  if (!input_file.open(dirsearch, task, &dummy))
    return false;

  std::string input_string;
  Lex::read_file(&input_file, &input_string);

  Lex lex(input_string.c_str(), input_string.length(), first_token);
  lex.set_mode(lex_mode);

  Parser_closure closure(filename,
			 cmdline->position_dependent_options(),
			 first_token == Lex::DYNAMIC_LIST,
			 false,
			 input_file.is_in_sysroot(),
                         cmdline,
			 script_options,
			 &lex,
			 false);
  if (yyparse(&closure) != 0)
    {
      input_file.file().unlock(task);
      return false;
    }

  input_file.file().unlock(task);

  gold_assert(!closure.saw_inputs());

  return true;
}

// FILENAME was found as an argument to --script (-T).
// Read it as a script, and execute its contents immediately.

bool
read_commandline_script(const char* filename, Command_line* cmdline)
{
  return read_script_file(filename, cmdline, &cmdline->script_options(),
                          PARSING_LINKER_SCRIPT, Lex::LINKER_SCRIPT);
}

// FILENAME was found as an argument to --version-script.  Read it as
// a version script, and store its contents in
// cmdline->script_options()->version_script_info().

bool
read_version_script(const char* filename, Command_line* cmdline)
{
  return read_script_file(filename, cmdline, &cmdline->script_options(),
                          PARSING_VERSION_SCRIPT, Lex::VERSION_SCRIPT);
}

// FILENAME was found as an argument to --dynamic-list.  Read it as a
// list of symbols, and store its contents in DYNAMIC_LIST.

bool
read_dynamic_list(const char* filename, Command_line* cmdline,
                  Script_options* dynamic_list)
{
  return read_script_file(filename, cmdline, dynamic_list,
                          PARSING_DYNAMIC_LIST, Lex::DYNAMIC_LIST);
}

// Implement the --defsym option on the command line.  Return true if
// all is well.

bool
Script_options::define_symbol(const char* definition)
{
  Lex lex(definition, strlen(definition), PARSING_DEFSYM);
  lex.set_mode(Lex::EXPRESSION);

  // Dummy value.
  Position_dependent_options posdep_options;

  Parser_closure closure("command line", posdep_options, true,
			 false, false, NULL, this, &lex, false);

  if (yyparse(&closure) != 0)
    return false;

  gold_assert(!closure.saw_inputs());

  return true;
}

// Print the script to F for debugging.

void
Script_options::print(FILE* f) const
{
  fprintf(f, "%s: Dumping linker script\n", program_name);

  if (!this->entry_.empty())
    fprintf(f, "ENTRY(%s)\n", this->entry_.c_str());

  for (Symbol_assignments::const_iterator p =
	 this->symbol_assignments_.begin();
       p != this->symbol_assignments_.end();
       ++p)
    (*p)->print(f);

  for (Assertions::const_iterator p = this->assertions_.begin();
       p != this->assertions_.end();
       ++p)
    (*p)->print(f);

  this->script_sections_.print(f);

  this->version_script_info_.print(f);
}

// Manage mapping from keywords to the codes expected by the bison
// parser.  We construct one global object for each lex mode with
// keywords.

class Keyword_to_parsecode
{
 public:
  // The structure which maps keywords to parsecodes.
  struct Keyword_parsecode
  {
    // Keyword.
    const char* keyword;
    // Corresponding parsecode.
    int parsecode;
  };

  Keyword_to_parsecode(const Keyword_parsecode* keywords,
                       int keyword_count)
      : keyword_parsecodes_(keywords), keyword_count_(keyword_count)
  { }

  // Return the parsecode corresponding KEYWORD, or 0 if it is not a
  // keyword.
  int
  keyword_to_parsecode(const char* keyword, size_t len) const;

 private:
  const Keyword_parsecode* keyword_parsecodes_;
  const int keyword_count_;
};

// Mapping from keyword string to keyword parsecode.  This array must
// be kept in sorted order.  Parsecodes are looked up using bsearch.
// This array must correspond to the list of parsecodes in yyscript.y.

static const Keyword_to_parsecode::Keyword_parsecode
script_keyword_parsecodes[] =
{
  { "ABSOLUTE", ABSOLUTE },
  { "ADDR", ADDR },
  { "ALIGN", ALIGN_K },
  { "ALIGNOF", ALIGNOF },
  { "ASSERT", ASSERT_K },
  { "AS_NEEDED", AS_NEEDED },
  { "AT", AT },
  { "BIND", BIND },
  { "BLOCK", BLOCK },
  { "BYTE", BYTE },
  { "CONSTANT", CONSTANT },
  { "CONSTRUCTORS", CONSTRUCTORS },
  { "COPY", COPY },
  { "CREATE_OBJECT_SYMBOLS", CREATE_OBJECT_SYMBOLS },
  { "DATA_SEGMENT_ALIGN", DATA_SEGMENT_ALIGN },
  { "DATA_SEGMENT_END", DATA_SEGMENT_END },
  { "DATA_SEGMENT_RELRO_END", DATA_SEGMENT_RELRO_END },
  { "DEFINED", DEFINED },
  { "DSECT", DSECT },
  { "ENTRY", ENTRY },
  { "EXCLUDE_FILE", EXCLUDE_FILE },
  { "EXTERN", EXTERN },
  { "FILL", FILL },
  { "FLOAT", FLOAT },
  { "FORCE_COMMON_ALLOCATION", FORCE_COMMON_ALLOCATION },
  { "GROUP", GROUP },
  { "HLL", HLL },
  { "INCLUDE", INCLUDE },
  { "INFO", INFO },
  { "INHIBIT_COMMON_ALLOCATION", INHIBIT_COMMON_ALLOCATION },
  { "INPUT", INPUT },
  { "KEEP", KEEP },
  { "LENGTH", LENGTH },
  { "LOADADDR", LOADADDR },
  { "LONG", LONG },
  { "MAP", MAP },
  { "MAX", MAX_K },
  { "MEMORY", MEMORY },
  { "MIN", MIN_K },
  { "NEXT", NEXT },
  { "NOCROSSREFS", NOCROSSREFS },
  { "NOFLOAT", NOFLOAT },
  { "NOLOAD", NOLOAD },
  { "ONLY_IF_RO", ONLY_IF_RO },
  { "ONLY_IF_RW", ONLY_IF_RW },
  { "OPTION", OPTION },
  { "ORIGIN", ORIGIN },
  { "OUTPUT", OUTPUT },
  { "OUTPUT_ARCH", OUTPUT_ARCH },
  { "OUTPUT_FORMAT", OUTPUT_FORMAT },
  { "OVERLAY", OVERLAY },
  { "PHDRS", PHDRS },
  { "PROVIDE", PROVIDE },
  { "PROVIDE_HIDDEN", PROVIDE_HIDDEN },
  { "QUAD", QUAD },
  { "SEARCH_DIR", SEARCH_DIR },
  { "SECTIONS", SECTIONS },
  { "SEGMENT_START", SEGMENT_START },
  { "SHORT", SHORT },
  { "SIZEOF", SIZEOF },
  { "SIZEOF_HEADERS", SIZEOF_HEADERS },
  { "SORT", SORT_BY_NAME },
  { "SORT_BY_ALIGNMENT", SORT_BY_ALIGNMENT },
  { "SORT_BY_NAME", SORT_BY_NAME },
  { "SPECIAL", SPECIAL },
  { "SQUAD", SQUAD },
  { "STARTUP", STARTUP },
  { "SUBALIGN", SUBALIGN },
  { "SYSLIB", SYSLIB },
  { "TARGET", TARGET_K },
  { "TRUNCATE", TRUNCATE },
  { "VERSION", VERSIONK },
  { "global", GLOBAL },
  { "l", LENGTH },
  { "len", LENGTH },
  { "local", LOCAL },
  { "o", ORIGIN },
  { "org", ORIGIN },
  { "sizeof_headers", SIZEOF_HEADERS },
};

static const Keyword_to_parsecode
script_keywords(&script_keyword_parsecodes[0],
                (sizeof(script_keyword_parsecodes)
                 / sizeof(script_keyword_parsecodes[0])));

static const Keyword_to_parsecode::Keyword_parsecode
version_script_keyword_parsecodes[] =
{
  { "extern", EXTERN },
  { "global", GLOBAL },
  { "local", LOCAL },
};

static const Keyword_to_parsecode
version_script_keywords(&version_script_keyword_parsecodes[0],
                        (sizeof(version_script_keyword_parsecodes)
                         / sizeof(version_script_keyword_parsecodes[0])));

static const Keyword_to_parsecode::Keyword_parsecode
dynamic_list_keyword_parsecodes[] =
{
  { "extern", EXTERN },
};

static const Keyword_to_parsecode
dynamic_list_keywords(&dynamic_list_keyword_parsecodes[0],
                      (sizeof(dynamic_list_keyword_parsecodes)
                       / sizeof(dynamic_list_keyword_parsecodes[0])));



// Comparison function passed to bsearch.

extern "C"
{

struct Ktt_key
{
  const char* str;
  size_t len;
};

static int
ktt_compare(const void* keyv, const void* kttv)
{
  const Ktt_key* key = static_cast<const Ktt_key*>(keyv);
  const Keyword_to_parsecode::Keyword_parsecode* ktt =
    static_cast<const Keyword_to_parsecode::Keyword_parsecode*>(kttv);
  int i = strncmp(key->str, ktt->keyword, key->len);
  if (i != 0)
    return i;
  if (ktt->keyword[key->len] != '\0')
    return -1;
  return 0;
}

} // End extern "C".

int
Keyword_to_parsecode::keyword_to_parsecode(const char* keyword,
                                           size_t len) const
{
  Ktt_key key;
  key.str = keyword;
  key.len = len;
  void* kttv = bsearch(&key,
                       this->keyword_parsecodes_,
                       this->keyword_count_,
                       sizeof(this->keyword_parsecodes_[0]),
                       ktt_compare);
  if (kttv == NULL)
    return 0;
  Keyword_parsecode* ktt = static_cast<Keyword_parsecode*>(kttv);
  return ktt->parsecode;
}

// The following structs are used within the VersionInfo class as well
// as in the bison helper functions.  They store the information
// parsed from the version script.

// A single version expression.
// For example, pattern="std::map*" and language="C++".
struct Version_expression
{
  Version_expression(const std::string& a_pattern,
		     Version_script_info::Language a_language,
                     bool a_exact_match)
    : pattern(a_pattern), language(a_language), exact_match(a_exact_match),
      was_matched_by_symbol(false)
  { }

  std::string pattern;
  Version_script_info::Language language;
  // If false, we use glob() to match pattern.  If true, we use strcmp().
  bool exact_match;
  // True if --no-undefined-version is in effect and we found this
  // version in get_symbol_version.  We use mutable because this
  // struct is generally not modifiable after it has been created.
  mutable bool was_matched_by_symbol;
};

// A list of expressions.
struct Version_expression_list
{
  std::vector<struct Version_expression> expressions;
};

// A list of which versions upon which another version depends.
// Strings should be from the Stringpool.
struct Version_dependency_list
{
  std::vector<std::string> dependencies;
};

// The total definition of a version.  It includes the tag for the
// version, its global and local expressions, and any dependencies.
struct Version_tree
{
  Version_tree()
      : tag(), global(NULL), local(NULL), dependencies(NULL)
  { }

  std::string tag;
  const struct Version_expression_list* global;
  const struct Version_expression_list* local;
  const struct Version_dependency_list* dependencies;
};

// Helper class that calls cplus_demangle when needed and takes care of freeing
// the result.

class Lazy_demangler
{
 public:
  Lazy_demangler(const char* symbol, int options)
    : symbol_(symbol), options_(options), demangled_(NULL), did_demangle_(false)
  { }

  ~Lazy_demangler()
  { free(this->demangled_); }

  // Return the demangled name. The actual demangling happens on the first call,
  // and the result is later cached.
  inline char*
  get();

 private:
  // The symbol to demangle.
  const char* symbol_;
  // Option flags to pass to cplus_demagle.
  const int options_;
  // The cached demangled value, or NULL if demangling didn't happen yet or
  // failed.
  char* demangled_;
  // Whether we already called cplus_demangle
  bool did_demangle_;
};

// Return the demangled name. The actual demangling happens on the first call,
// and the result is later cached. Returns NULL if the symbol cannot be
// demangled.

inline char*
Lazy_demangler::get()
{
  if (!this->did_demangle_)
    {
      this->demangled_ = cplus_demangle(this->symbol_, this->options_);
      this->did_demangle_ = true;
    }
  return this->demangled_;
}

// Class Version_script_info.

Version_script_info::Version_script_info()
  : dependency_lists_(), expression_lists_(), version_trees_(), globs_(),
    default_version_(NULL), default_is_global_(false), is_finalized_(false)
{
  for (int i = 0; i < LANGUAGE_COUNT; ++i)
    this->exact_[i] = NULL;
}

Version_script_info::~Version_script_info()
{
}

// Forget all the known version script information.

void
Version_script_info::clear()
{
  for (size_t k = 0; k < this->dependency_lists_.size(); ++k)
    delete this->dependency_lists_[k];
  this->dependency_lists_.clear();
  for (size_t k = 0; k < this->version_trees_.size(); ++k)
    delete this->version_trees_[k];
  this->version_trees_.clear();
  for (size_t k = 0; k < this->expression_lists_.size(); ++k)
    delete this->expression_lists_[k];
  this->expression_lists_.clear();
}

// Finalize the version script information.

void
Version_script_info::finalize()
{
  if (!this->is_finalized_)
    {
      this->build_lookup_tables();
      this->is_finalized_ = true;
    }
}

// Return all the versions.

std::vector<std::string>
Version_script_info::get_versions() const
{
  std::vector<std::string> ret;
  for (size_t j = 0; j < this->version_trees_.size(); ++j)
    if (!this->version_trees_[j]->tag.empty())
      ret.push_back(this->version_trees_[j]->tag);
  return ret;
}

// Return the dependencies of VERSION.

std::vector<std::string>
Version_script_info::get_dependencies(const char* version) const
{
  std::vector<std::string> ret;
  for (size_t j = 0; j < this->version_trees_.size(); ++j)
    if (this->version_trees_[j]->tag == version)
      {
        const struct Version_dependency_list* deps =
          this->version_trees_[j]->dependencies;
        if (deps != NULL)
          for (size_t k = 0; k < deps->dependencies.size(); ++k)
            ret.push_back(deps->dependencies[k]);
        return ret;
      }
  return ret;
}

// A version script essentially maps a symbol name to a version tag
// and an indication of whether symbol is global or local within that
// version tag.  Each symbol maps to at most one version tag.
// Unfortunately, in practice, version scripts are ambiguous, and list
// symbols multiple times.  Thus, we have to document the matching
// process.

// This is a description of what the GNU linker does as of 2010-01-11.
// It walks through the version tags in the order in which they appear
// in the version script.  For each tag, it first walks through the
// global patterns for that tag, then the local patterns.  When
// looking at a single pattern, it first applies any language specific
// demangling as specified for the pattern, and then matches the
// resulting symbol name to the pattern.  If it finds an exact match
// for a literal pattern (a pattern enclosed in quotes or with no
// wildcard characters), then that is the match that it uses.  If
// finds a match with a wildcard pattern, then it saves it and
// continues searching.  Wildcard patterns that are exactly "*" are
// saved separately.

// If no exact match with a literal pattern is ever found, then if a
// wildcard match with a global pattern was found it is used,
// otherwise if a wildcard match with a local pattern was found it is
// used.

// This is the result:
//   * If there is an exact match, then we use the first tag in the
//     version script where it matches.
//     + If the exact match in that tag is global, it is used.
//     + Otherwise the exact match in that tag is local, and is used.
//   * Otherwise, if there is any match with a global wildcard pattern:
//     + If there is any match with a wildcard pattern which is not
//       "*", then we use the tag in which the *last* such pattern
//       appears.
//     + Otherwise, we matched "*".  If there is no match with a local
//       wildcard pattern which is not "*", then we use the *last*
//       match with a global "*".  Otherwise, continue.
//   * Otherwise, if there is any match with a local wildcard pattern:
//     + If there is any match with a wildcard pattern which is not
//       "*", then we use the tag in which the *last* such pattern
//       appears.
//     + Otherwise, we matched "*", and we use the tag in which the
//       *last* such match occurred.

// There is an additional wrinkle.  When the GNU linker finds a symbol
// with a version defined in an object file due to a .symver
// directive, it looks up that symbol name in that version tag.  If it
// finds it, it matches the symbol name against the patterns for that
// version.  If there is no match with a global pattern, but there is
// a match with a local pattern, then the GNU linker marks the symbol
// as local.

// We want gold to be generally compatible, but we also want gold to
// be fast.  These are the rules that gold implements:
//   * If there is an exact match for the mangled name, we use it.
//     + If there is more than one exact match, we give a warning, and
//       we use the first tag in the script which matches.
//     + If a symbol has an exact match as both global and local for
//       the same version tag, we give an error.
//   * Otherwise, we look for an extern C++ or an extern Java exact
//     match.  If we find an exact match, we use it.
//     + If there is more than one exact match, we give a warning, and
//       we use the first tag in the script which matches.
//     + If a symbol has an exact match as both global and local for
//       the same version tag, we give an error.
//   * Otherwise, we look through the wildcard patterns, ignoring "*"
//     patterns.  We look through the version tags in reverse order.
//     For each version tag, we look through the global patterns and
//     then the local patterns.  We use the first match we find (i.e.,
//     the last matching version tag in the file).
//   * Otherwise, we use the "*" pattern if there is one.  We give an
//     error if there are multiple "*" patterns.

// At least for now, gold does not look up the version tag for a
// symbol version found in an object file to see if it should be
// forced local.  There are other ways to force a symbol to be local,
// and I don't understand why this one is useful.

// Build a set of fast lookup tables for a version script.

void
Version_script_info::build_lookup_tables()
{
  size_t size = this->version_trees_.size();
  for (size_t j = 0; j < size; ++j)
    {
      const Version_tree* v = this->version_trees_[j];
      this->build_expression_list_lookup(v->local, v, false);
      this->build_expression_list_lookup(v->global, v, true);
    }
}

// If a pattern has backlashes but no unquoted wildcard characters,
// then we apply backslash unquoting and look for an exact match.
// Otherwise we treat it as a wildcard pattern.  This function returns
// true for a wildcard pattern.  Otherwise, it does backslash
// unquoting on *PATTERN and returns false.  If this returns true,
// *PATTERN may have been partially unquoted.

bool
Version_script_info::unquote(std::string* pattern) const
{
  bool saw_backslash = false;
  size_t len = pattern->length();
  size_t j = 0;
  for (size_t i = 0; i < len; ++i)
    {
      if (saw_backslash)
	saw_backslash = false;
      else
	{
	  switch ((*pattern)[i])
	    {
	    case '?': case '[': case '*':
	      return true;
	    case '\\':
	      saw_backslash = true;
	      continue;
	    default:
	      break;
	    }
	}

      if (i != j)
	(*pattern)[j] = (*pattern)[i];
      ++j;
    }
  return false;
}

// Add an exact match for MATCH to *PE.  The result of the match is
// V/IS_GLOBAL.

void
Version_script_info::add_exact_match(const std::string& match,
				     const Version_tree* v, bool is_global,
				     const Version_expression* ve,
				     Exact* pe)
{
  std::pair<Exact::iterator, bool> ins =
    pe->insert(std::make_pair(match, Version_tree_match(v, is_global, ve)));
  if (ins.second)
    {
      // This is the first time we have seen this match.
      return;
    }

  Version_tree_match& vtm(ins.first->second);
  if (vtm.real->tag != v->tag)
    {
      // This is an ambiguous match.  We still return the
      // first version that we found in the script, but we
      // record the new version to issue a warning if we
      // wind up looking up this symbol.
      if (vtm.ambiguous == NULL)
	vtm.ambiguous = v;
    }
  else if (is_global != vtm.is_global)
    {
      // We have a match for both the global and local entries for a
      // version tag.  That's got to be wrong.
      gold_error(_("'%s' appears as both a global and a local symbol "
		   "for version '%s' in script"),
		 match.c_str(), v->tag.c_str());
    }
}

// Build fast lookup information for EXPLIST and store it in LOOKUP.
// All matches go to V, and IS_GLOBAL is true if they are global
// matches.

void
Version_script_info::build_expression_list_lookup(
    const Version_expression_list* explist,
    const Version_tree* v,
    bool is_global)
{
  if (explist == NULL)
    return;
  size_t size = explist->expressions.size();
  for (size_t i = 0; i < size; ++i)
    {
      const Version_expression& exp(explist->expressions[i]);

      if (exp.pattern.length() == 1 && exp.pattern[0] == '*')
	{
	  if (this->default_version_ != NULL
	      && this->default_version_->tag != v->tag)
	    gold_warning(_("wildcard match appears in both version '%s' "
			   "and '%s' in script"),
			 this->default_version_->tag.c_str(), v->tag.c_str());
	  else if (this->default_version_ != NULL
		   && this->default_is_global_ != is_global)
	    gold_error(_("wildcard match appears as both global and local "
			 "in version '%s' in script"),
		       v->tag.c_str());
	  this->default_version_ = v;
	  this->default_is_global_ = is_global;
	  continue;
	}

      std::string pattern = exp.pattern;
      if (!exp.exact_match)
	{
	  if (this->unquote(&pattern))
	    {
	      this->globs_.push_back(Glob(&exp, v, is_global));
	      continue;
	    }
	}

      if (this->exact_[exp.language] == NULL)
	this->exact_[exp.language] = new Exact();
      this->add_exact_match(pattern, v, is_global, &exp,
			    this->exact_[exp.language]);
    }
}

// Return the name to match given a name, a language code, and two
// lazy demanglers.

const char*
Version_script_info::get_name_to_match(const char* name,
				       int language,
				       Lazy_demangler* cpp_demangler,
				       Lazy_demangler* java_demangler) const
{
  switch (language)
    {
    case LANGUAGE_C:
      return name;
    case LANGUAGE_CXX:
      return cpp_demangler->get();
    case LANGUAGE_JAVA:
      return java_demangler->get();
    default:
      gold_unreachable();
    }
}

// Look up SYMBOL_NAME in the list of versions.  Return true if the
// symbol is found, false if not.  If the symbol is found, then if
// PVERSION is not NULL, set *PVERSION to the version tag, and if
// P_IS_GLOBAL is not NULL, set *P_IS_GLOBAL according to whether the
// symbol is global or not.

bool
Version_script_info::get_symbol_version(const char* symbol_name,
					std::string* pversion,
					bool* p_is_global) const
{
  Lazy_demangler cpp_demangled_name(symbol_name, DMGL_ANSI | DMGL_PARAMS);
  Lazy_demangler java_demangled_name(symbol_name,
				     DMGL_ANSI | DMGL_PARAMS | DMGL_JAVA);

  gold_assert(this->is_finalized_);
  for (int i = 0; i < LANGUAGE_COUNT; ++i)
    {
      Exact* exact = this->exact_[i];
      if (exact == NULL)
	continue;

      const char* name_to_match = this->get_name_to_match(symbol_name, i,
							  &cpp_demangled_name,
							  &java_demangled_name);
      if (name_to_match == NULL)
	{
	  // If the name can not be demangled, the GNU linker goes
	  // ahead and tries to match it anyhow.  That does not
	  // make sense to me and I have not implemented it.
	  continue;
	}

      Exact::const_iterator pe = exact->find(name_to_match);
      if (pe != exact->end())
	{
	  const Version_tree_match& vtm(pe->second);
	  if (vtm.ambiguous != NULL)
	    gold_warning(_("using '%s' as version for '%s' which is also "
			   "named in version '%s' in script"),
			 vtm.real->tag.c_str(), name_to_match,
			 vtm.ambiguous->tag.c_str());

	  if (pversion != NULL)
	    *pversion = vtm.real->tag;
	  if (p_is_global != NULL)
	    *p_is_global = vtm.is_global;

	  // If we are using --no-undefined-version, and this is a
	  // global symbol, we have to record that we have found this
	  // symbol, so that we don't warn about it.  We have to do
	  // this now, because otherwise we have no way to get from a
	  // non-C language back to the demangled name that we
	  // matched.
	  if (p_is_global != NULL && vtm.is_global)
	    vtm.expression->was_matched_by_symbol = true;

	  return true;
	}
    }

  // Look through the glob patterns in reverse order.

  for (Globs::const_reverse_iterator p = this->globs_.rbegin();
       p != this->globs_.rend();
       ++p)
    {
      int language = p->expression->language;
      const char* name_to_match = this->get_name_to_match(symbol_name,
							  language,
							  &cpp_demangled_name,
							  &java_demangled_name);
      if (name_to_match == NULL)
	continue;

      if (fnmatch(p->expression->pattern.c_str(), name_to_match,
		  FNM_NOESCAPE) == 0)
	{
	  if (pversion != NULL)
	    *pversion = p->version->tag;
	  if (p_is_global != NULL)
	    *p_is_global = p->is_global;
	  return true;
	}
    }

  // Finally, there may be a wildcard.
  if (this->default_version_ != NULL)
    {
      if (pversion != NULL)
	*pversion = this->default_version_->tag;
      if (p_is_global != NULL)
	*p_is_global = this->default_is_global_;
      return true;
    }

  return false;
}

// Give an error if any exact symbol names (not wildcards) appear in a
// version script, but there is no such symbol.

void
Version_script_info::check_unmatched_names(const Symbol_table* symtab) const
{
  for (size_t i = 0; i < this->version_trees_.size(); ++i)
    {
      const Version_tree* vt = this->version_trees_[i];
      if (vt->global == NULL)
	continue;
      for (size_t j = 0; j < vt->global->expressions.size(); ++j)
	{
	  const Version_expression& expression(vt->global->expressions[j]);

	  // Ignore cases where we used the version because we saw a
	  // symbol that we looked up.  Note that
	  // WAS_MATCHED_BY_SYMBOL will be true even if the symbol was
	  // not a definition.  That's OK as in that case we most
	  // likely gave an undefined symbol error anyhow.
	  if (expression.was_matched_by_symbol)
	    continue;

	  // Just ignore names which are in languages other than C.
	  // We have no way to look them up in the symbol table.
	  if (expression.language != LANGUAGE_C)
	    continue;

	  // Remove backslash quoting, and ignore wildcard patterns.
	  std::string pattern = expression.pattern;
	  if (!expression.exact_match)
	    {
	      if (this->unquote(&pattern))
		continue;
	    }

	  if (symtab->lookup(pattern.c_str(), vt->tag.c_str()) == NULL)
	    gold_error(_("version script assignment of %s to symbol %s "
			 "failed: symbol not defined"),
		       vt->tag.c_str(), pattern.c_str());
	}
    }
}

struct Version_dependency_list*
Version_script_info::allocate_dependency_list()
{
  dependency_lists_.push_back(new Version_dependency_list);
  return dependency_lists_.back();
}

struct Version_expression_list*
Version_script_info::allocate_expression_list()
{
  expression_lists_.push_back(new Version_expression_list);
  return expression_lists_.back();
}

struct Version_tree*
Version_script_info::allocate_version_tree()
{
  version_trees_.push_back(new Version_tree);
  return version_trees_.back();
}

// Print for debugging.

void
Version_script_info::print(FILE* f) const
{
  if (this->empty())
    return;

  fprintf(f, "VERSION {");

  for (size_t i = 0; i < this->version_trees_.size(); ++i)
    {
      const Version_tree* vt = this->version_trees_[i];

      if (vt->tag.empty())
	fprintf(f, "  {\n");
      else
	fprintf(f, "  %s {\n", vt->tag.c_str());

      if (vt->global != NULL)
	{
	  fprintf(f, "    global :\n");
	  this->print_expression_list(f, vt->global);
	}

      if (vt->local != NULL)
	{
	  fprintf(f, "    local :\n");
	  this->print_expression_list(f, vt->local);
	}

      fprintf(f, "  }");
      if (vt->dependencies != NULL)
	{
	  const Version_dependency_list* deps = vt->dependencies;
	  for (size_t j = 0; j < deps->dependencies.size(); ++j)
	    {
	      if (j < deps->dependencies.size() - 1)
		fprintf(f, "\n");
	      fprintf(f, "    %s", deps->dependencies[j].c_str());
	    }
	}
      fprintf(f, ";\n");
    }

  fprintf(f, "}\n");
}

void
Version_script_info::print_expression_list(
    FILE* f,
    const Version_expression_list* vel) const
{
  Version_script_info::Language current_language = LANGUAGE_C;
  for (size_t i = 0; i < vel->expressions.size(); ++i)
    {
      const Version_expression& ve(vel->expressions[i]);

      if (ve.language != current_language)
	{
	  if (current_language != LANGUAGE_C)
	    fprintf(f, "      }\n");
	  switch (ve.language)
	    {
	    case LANGUAGE_C:
	      break;
	    case LANGUAGE_CXX:
	      fprintf(f, "      extern \"C++\" {\n");
	      break;
	    case LANGUAGE_JAVA:
	      fprintf(f, "      extern \"Java\" {\n");
	      break;
	    default:
	      gold_unreachable();
	    }
	  current_language = ve.language;
	}

      fprintf(f, "      ");
      if (current_language != LANGUAGE_C)
	fprintf(f, "  ");

      if (ve.exact_match)
	fprintf(f, "\"");
      fprintf(f, "%s", ve.pattern.c_str());
      if (ve.exact_match)
	fprintf(f, "\"");

      fprintf(f, "\n");
    }

  if (current_language != LANGUAGE_C)
    fprintf(f, "      }\n");
}

} // End namespace gold.

// The remaining functions are extern "C", so it's clearer to not put
// them in namespace gold.

using namespace gold;

// This function is called by the bison parser to return the next
// token.

extern "C" int
yylex(YYSTYPE* lvalp, void* closurev)
{
  Parser_closure* closure = static_cast<Parser_closure*>(closurev);
  const Token* token = closure->next_token();
  switch (token->classification())
    {
    default:
      gold_unreachable();

    case Token::TOKEN_INVALID:
      yyerror(closurev, "invalid character");
      return 0;

    case Token::TOKEN_EOF:
      return 0;

    case Token::TOKEN_STRING:
      {
	// This is either a keyword or a STRING.
	size_t len;
	const char* str = token->string_value(&len);
	int parsecode = 0;
        switch (closure->lex_mode())
          {
          case Lex::LINKER_SCRIPT:
            parsecode = script_keywords.keyword_to_parsecode(str, len);
            break;
          case Lex::VERSION_SCRIPT:
            parsecode = version_script_keywords.keyword_to_parsecode(str, len);
            break;
          case Lex::DYNAMIC_LIST:
            parsecode = dynamic_list_keywords.keyword_to_parsecode(str, len);
            break;
          default:
            break;
          }
	if (parsecode != 0)
	  return parsecode;
	lvalp->string.value = str;
	lvalp->string.length = len;
	return STRING;
      }

    case Token::TOKEN_QUOTED_STRING:
      lvalp->string.value = token->string_value(&lvalp->string.length);
      return QUOTED_STRING;

    case Token::TOKEN_OPERATOR:
      return token->operator_value();

    case Token::TOKEN_INTEGER:
      lvalp->integer = token->integer_value();
      return INTEGER;
    }
}

// This function is called by the bison parser to report an error.

extern "C" void
yyerror(void* closurev, const char* message)
{
  Parser_closure* closure = static_cast<Parser_closure*>(closurev);
  gold_error(_("%s:%d:%d: %s"), closure->filename(), closure->lineno(),
	     closure->charpos(), message);
}

// Called by the bison parser to add an external symbol to the link.

extern "C" void
script_add_extern(void* closurev, const char* name, size_t length)
{
  // We treat exactly like -u NAME.  FIXME: If it seems useful, we
  // could handle this after the command line has been read, by adding
  // entries to the symbol table directly.
  std::string arg("--undefined=");
  arg.append(name, length);
  script_parse_option(closurev, arg.c_str(), arg.size());
}

// Called by the bison parser to add a file to the link.

extern "C" void
script_add_file(void* closurev, const char* name, size_t length)
{
  Parser_closure* closure = static_cast<Parser_closure*>(closurev);

  // If this is an absolute path, and we found the script in the
  // sysroot, then we want to prepend the sysroot to the file name.
  // For example, this is how we handle a cross link to the x86_64
  // libc.so, which refers to /lib/libc.so.6.
  std::string name_string(name, length);
  const char* extra_search_path = ".";
  std::string script_directory;
  if (IS_ABSOLUTE_PATH(name_string.c_str()))
    {
      if (closure->is_in_sysroot())
	{
	  const std::string& sysroot(parameters->options().sysroot());
	  gold_assert(!sysroot.empty());
	  name_string = sysroot + name_string;
	}
    }
  else
    {
      // In addition to checking the normal library search path, we
      // also want to check in the script-directory.
      const char* slash = strrchr(closure->filename(), '/');
      if (slash != NULL)
	{
	  script_directory.assign(closure->filename(),
				  slash - closure->filename() + 1);
	  extra_search_path = script_directory.c_str();
	}
    }

  Input_file_argument file(name_string.c_str(),
			   Input_file_argument::INPUT_FILE_TYPE_FILE,
			   extra_search_path, false,
			   closure->position_dependent_options());
  closure->inputs()->add_file(file);
}

// Called by the bison parser to add a library to the link.

extern "C" void
script_add_library(void* closurev, const char* name, size_t length)
{
  Parser_closure* closure = static_cast<Parser_closure*>(closurev);
  std::string name_string(name, length);

  if (name_string[0] != 'l')
    gold_error(_("library name must be prefixed with -l"));
    
  Input_file_argument file(name_string.c_str() + 1,
			   Input_file_argument::INPUT_FILE_TYPE_LIBRARY,
			   "", false,
			   closure->position_dependent_options());
  closure->inputs()->add_file(file);
}

// Called by the bison parser to start a group.  If we are already in
// a group, that means that this script was invoked within a
// --start-group --end-group sequence on the command line, or that
// this script was found in a GROUP of another script.  In that case,
// we simply continue the existing group, rather than starting a new
// one.  It is possible to construct a case in which this will do
// something other than what would happen if we did a recursive group,
// but it's hard to imagine why the different behaviour would be
// useful for a real program.  Avoiding recursive groups is simpler
// and more efficient.

extern "C" void
script_start_group(void* closurev)
{
  Parser_closure* closure = static_cast<Parser_closure*>(closurev);
  if (!closure->in_group())
    closure->inputs()->start_group();
}

// Called by the bison parser at the end of a group.

extern "C" void
script_end_group(void* closurev)
{
  Parser_closure* closure = static_cast<Parser_closure*>(closurev);
  if (!closure->in_group())
    closure->inputs()->end_group();
}

// Called by the bison parser to start an AS_NEEDED list.

extern "C" void
script_start_as_needed(void* closurev)
{
  Parser_closure* closure = static_cast<Parser_closure*>(closurev);
  closure->position_dependent_options().set_as_needed(true);
}

// Called by the bison parser at the end of an AS_NEEDED list.

extern "C" void
script_end_as_needed(void* closurev)
{
  Parser_closure* closure = static_cast<Parser_closure*>(closurev);
  closure->position_dependent_options().set_as_needed(false);
}

// Called by the bison parser to set the entry symbol.

extern "C" void
script_set_entry(void* closurev, const char* entry, size_t length)
{
  // We'll parse this exactly the same as --entry=ENTRY on the commandline
  // TODO(csilvers): FIXME -- call set_entry directly.
  std::string arg("--entry=");
  arg.append(entry, length);
  script_parse_option(closurev, arg.c_str(), arg.size());
}

// Called by the bison parser to set whether to define common symbols.

extern "C" void
script_set_common_allocation(void* closurev, int set)
{
  const char* arg = set != 0 ? "--define-common" : "--no-define-common";
  script_parse_option(closurev, arg, strlen(arg));
}

// Called by the bison parser to refer to a symbol.

extern "C" Expression*
script_symbol(void* closurev, const char* name, size_t length)
{
  Parser_closure* closure = static_cast<Parser_closure*>(closurev);
  if (length != 1 || name[0] != '.')
    closure->script_options()->add_symbol_reference(name, length);
  return script_exp_string(name, length);
}

// Called by the bison parser to define a symbol.

extern "C" void
script_set_symbol(void* closurev, const char* name, size_t length,
		  Expression* value, int providei, int hiddeni)
{
  Parser_closure* closure = static_cast<Parser_closure*>(closurev);
  const bool provide = providei != 0;
  const bool hidden = hiddeni != 0;
  closure->script_options()->add_symbol_assignment(name, length,
						   closure->parsing_defsym(),
						   value, provide, hidden);
  closure->clear_skip_on_incompatible_target();
}

// Called by the bison parser to add an assertion.

extern "C" void
script_add_assertion(void* closurev, Expression* check, const char* message,
		     size_t messagelen)
{
  Parser_closure* closure = static_cast<Parser_closure*>(closurev);
  closure->script_options()->add_assertion(check, message, messagelen);
  closure->clear_skip_on_incompatible_target();
}

// Called by the bison parser to parse an OPTION.

extern "C" void
script_parse_option(void* closurev, const char* option, size_t length)
{
  Parser_closure* closure = static_cast<Parser_closure*>(closurev);
  // We treat the option as a single command-line option, even if
  // it has internal whitespace.
  if (closure->command_line() == NULL)
    {
      // There are some options that we could handle here--e.g.,
      // -lLIBRARY.  Should we bother?
      gold_warning(_("%s:%d:%d: ignoring command OPTION; OPTION is only valid"
		     " for scripts specified via -T/--script"),
		   closure->filename(), closure->lineno(), closure->charpos());
    }
  else
    {
      bool past_a_double_dash_option = false;
      const char* mutable_option = strndup(option, length);
      gold_assert(mutable_option != NULL);
      closure->command_line()->process_one_option(1, &mutable_option, 0,
                                                  &past_a_double_dash_option);
      // The General_options class will quite possibly store a pointer
      // into mutable_option, so we can't free it.  In cases the class
      // does not store such a pointer, this is a memory leak.  Alas. :(
    }
  closure->clear_skip_on_incompatible_target();
}

// Called by the bison parser to handle OUTPUT_FORMAT.  OUTPUT_FORMAT
// takes either one or three arguments.  In the three argument case,
// the format depends on the endianness option, which we don't
// currently support (FIXME).  If we see an OUTPUT_FORMAT for the
// wrong format, then we want to search for a new file.  Returning 0
// here will cause the parser to immediately abort.

extern "C" int
script_check_output_format(void* closurev,
			   const char* default_name, size_t default_length,
			   const char*, size_t, const char*, size_t)
{
  Parser_closure* closure = static_cast<Parser_closure*>(closurev);
  std::string name(default_name, default_length);
  Target* target = select_target_by_name(name.c_str());
  if (target == NULL || !parameters->is_compatible_target(target))
    {
      if (closure->skip_on_incompatible_target())
	{
	  closure->set_found_incompatible_target();
	  return 0;
	}
      // FIXME: Should we warn about the unknown target?
    }
  return 1;
}

// Called by the bison parser to handle TARGET.

extern "C" void
script_set_target(void* closurev, const char* target, size_t len)
{
  Parser_closure* closure = static_cast<Parser_closure*>(closurev);
  std::string s(target, len);
  General_options::Object_format format_enum;
  format_enum = General_options::string_to_object_format(s.c_str());
  closure->position_dependent_options().set_format_enum(format_enum);
}

// Called by the bison parser to handle SEARCH_DIR.  This is handled
// exactly like a -L option.

extern "C" void
script_add_search_dir(void* closurev, const char* option, size_t length)
{
  Parser_closure* closure = static_cast<Parser_closure*>(closurev);
  if (closure->command_line() == NULL)
    gold_warning(_("%s:%d:%d: ignoring SEARCH_DIR; SEARCH_DIR is only valid"
		   " for scripts specified via -T/--script"),
		 closure->filename(), closure->lineno(), closure->charpos());
  else if (!closure->command_line()->options().nostdlib())
    {
      std::string s = "-L" + std::string(option, length);
      script_parse_option(closurev, s.c_str(), s.size());
    }
}

/* Called by the bison parser to push the lexer into expression
   mode.  */

extern "C" void
script_push_lex_into_expression_mode(void* closurev)
{
  Parser_closure* closure = static_cast<Parser_closure*>(closurev);
  closure->push_lex_mode(Lex::EXPRESSION);
}

/* Called by the bison parser to push the lexer into version
   mode.  */

extern "C" void
script_push_lex_into_version_mode(void* closurev)
{
  Parser_closure* closure = static_cast<Parser_closure*>(closurev);
  if (closure->version_script()->is_finalized())
    gold_error(_("%s:%d:%d: invalid use of VERSION in input file"),
	       closure->filename(), closure->lineno(), closure->charpos());
  closure->push_lex_mode(Lex::VERSION_SCRIPT);
}

/* Called by the bison parser to pop the lexer mode.  */

extern "C" void
script_pop_lex_mode(void* closurev)
{
  Parser_closure* closure = static_cast<Parser_closure*>(closurev);
  closure->pop_lex_mode();
}

// Register an entire version node. For example:
//
// GLIBC_2.1 {
//   global: foo;
// } GLIBC_2.0;
//
// - tag is "GLIBC_2.1"
// - tree contains the information "global: foo"
// - deps contains "GLIBC_2.0"

extern "C" void
script_register_vers_node(void*,
			  const char* tag,
			  int taglen,
			  struct Version_tree* tree,
			  struct Version_dependency_list* deps)
{
  gold_assert(tree != NULL);
  tree->dependencies = deps;
  if (tag != NULL)
    tree->tag = std::string(tag, taglen);
}

// Add a dependencies to the list of existing dependencies, if any,
// and return the expanded list.

extern "C" struct Version_dependency_list*
script_add_vers_depend(void* closurev,
		       struct Version_dependency_list* all_deps,
		       const char* depend_to_add, int deplen)
{
  Parser_closure* closure = static_cast<Parser_closure*>(closurev);
  if (all_deps == NULL)
    all_deps = closure->version_script()->allocate_dependency_list();
  all_deps->dependencies.push_back(std::string(depend_to_add, deplen));
  return all_deps;
}

// Add a pattern expression to an existing list of expressions, if any.

extern "C" struct Version_expression_list*
script_new_vers_pattern(void* closurev,
			struct Version_expression_list* expressions,
			const char* pattern, int patlen, int exact_match)
{
  Parser_closure* closure = static_cast<Parser_closure*>(closurev);
  if (expressions == NULL)
    expressions = closure->version_script()->allocate_expression_list();
  expressions->expressions.push_back(
      Version_expression(std::string(pattern, patlen),
                         closure->get_current_language(),
                         static_cast<bool>(exact_match)));
  return expressions;
}

// Attaches b to the end of a, and clears b.  So a = a + b and b = {}.

extern "C" struct Version_expression_list*
script_merge_expressions(struct Version_expression_list* a,
                         struct Version_expression_list* b)
{
  a->expressions.insert(a->expressions.end(),
                        b->expressions.begin(), b->expressions.end());
  // We could delete b and remove it from expressions_lists_, but
  // that's a lot of work.  This works just as well.
  b->expressions.clear();
  return a;
}

// Combine the global and local expressions into a a Version_tree.

extern "C" struct Version_tree*
script_new_vers_node(void* closurev,
		     struct Version_expression_list* global,
		     struct Version_expression_list* local)
{
  Parser_closure* closure = static_cast<Parser_closure*>(closurev);
  Version_tree* tree = closure->version_script()->allocate_version_tree();
  tree->global = global;
  tree->local = local;
  return tree;
}

// Handle a transition in language, such as at the
// start or end of 'extern "C++"'

extern "C" void
version_script_push_lang(void* closurev, const char* lang, int langlen)
{
  Parser_closure* closure = static_cast<Parser_closure*>(closurev);
  std::string language(lang, langlen);
  Version_script_info::Language code;
  if (language.empty() || language == "C")
    code = Version_script_info::LANGUAGE_C;
  else if (language == "C++")
    code = Version_script_info::LANGUAGE_CXX;
  else if (language == "Java")
    code = Version_script_info::LANGUAGE_JAVA;
  else
    {
      char* buf = new char[langlen + 100];
      snprintf(buf, langlen + 100,
	       _("unrecognized version script language '%s'"),
	       language.c_str());
      yyerror(closurev, buf);
      delete[] buf;
      code = Version_script_info::LANGUAGE_C;
    }
  closure->push_language(code);
}

extern "C" void
version_script_pop_lang(void* closurev)
{
  Parser_closure* closure = static_cast<Parser_closure*>(closurev);
  closure->pop_language();
}

// Called by the bison parser to start a SECTIONS clause.

extern "C" void
script_start_sections(void* closurev)
{
  Parser_closure* closure = static_cast<Parser_closure*>(closurev);
  closure->script_options()->script_sections()->start_sections();
  closure->clear_skip_on_incompatible_target();
}

// Called by the bison parser to finish a SECTIONS clause.

extern "C" void
script_finish_sections(void* closurev)
{
  Parser_closure* closure = static_cast<Parser_closure*>(closurev);
  closure->script_options()->script_sections()->finish_sections();
}

// Start processing entries for an output section.

extern "C" void
script_start_output_section(void* closurev, const char* name, size_t namelen,
			    const struct Parser_output_section_header* header)
{
  Parser_closure* closure = static_cast<Parser_closure*>(closurev);
  closure->script_options()->script_sections()->start_output_section(name,
								     namelen,
								     header);
}

// Finish processing entries for an output section.

extern "C" void
script_finish_output_section(void* closurev,
			     const struct Parser_output_section_trailer* trail)
{
  Parser_closure* closure = static_cast<Parser_closure*>(closurev);
  closure->script_options()->script_sections()->finish_output_section(trail);
}

// Add a data item (e.g., "WORD (0)") to the current output section.

extern "C" void
script_add_data(void* closurev, int data_token, Expression* val)
{
  Parser_closure* closure = static_cast<Parser_closure*>(closurev);
  int size;
  bool is_signed = true;
  switch (data_token)
    {
    case QUAD:
      size = 8;
      is_signed = false;
      break;
    case SQUAD:
      size = 8;
      break;
    case LONG:
      size = 4;
      break;
    case SHORT:
      size = 2;
      break;
    case BYTE:
      size = 1;
      break;
    default:
      gold_unreachable();
    }
  closure->script_options()->script_sections()->add_data(size, is_signed, val);
}

// Add a clause setting the fill value to the current output section.

extern "C" void
script_add_fill(void* closurev, Expression* val)
{
  Parser_closure* closure = static_cast<Parser_closure*>(closurev);
  closure->script_options()->script_sections()->add_fill(val);
}

// Add a new input section specification to the current output
// section.

extern "C" void
script_add_input_section(void* closurev,
			 const struct Input_section_spec* spec,
			 int keepi)
{
  Parser_closure* closure = static_cast<Parser_closure*>(closurev);
  bool keep = keepi != 0;
  closure->script_options()->script_sections()->add_input_section(spec, keep);
}

// When we see DATA_SEGMENT_ALIGN we record that following output
// sections may be relro.

extern "C" void
script_data_segment_align(void* closurev)
{
  Parser_closure* closure = static_cast<Parser_closure*>(closurev);
  if (!closure->script_options()->saw_sections_clause())
    gold_error(_("%s:%d:%d: DATA_SEGMENT_ALIGN not in SECTIONS clause"),
	       closure->filename(), closure->lineno(), closure->charpos());
  else
    closure->script_options()->script_sections()->data_segment_align();
}

// When we see DATA_SEGMENT_RELRO_END we know that all output sections
// since DATA_SEGMENT_ALIGN should be relro.

extern "C" void
script_data_segment_relro_end(void* closurev)
{
  Parser_closure* closure = static_cast<Parser_closure*>(closurev);
  if (!closure->script_options()->saw_sections_clause())
    gold_error(_("%s:%d:%d: DATA_SEGMENT_ALIGN not in SECTIONS clause"),
	       closure->filename(), closure->lineno(), closure->charpos());
  else
    closure->script_options()->script_sections()->data_segment_relro_end();
}

// Create a new list of string/sort pairs.

extern "C" String_sort_list_ptr
script_new_string_sort_list(const struct Wildcard_section* string_sort)
{
  return new String_sort_list(1, *string_sort);
}

// Add an entry to a list of string/sort pairs.  The way the parser
// works permits us to simply modify the first parameter, rather than
// copy the vector.

extern "C" String_sort_list_ptr
script_string_sort_list_add(String_sort_list_ptr pv,
			    const struct Wildcard_section* string_sort)
{
  if (pv == NULL)
    return script_new_string_sort_list(string_sort);
  else
    {
      pv->push_back(*string_sort);
      return pv;
    }
}

// Create a new list of strings.

extern "C" String_list_ptr
script_new_string_list(const char* str, size_t len)
{
  return new String_list(1, std::string(str, len));
}

// Add an element to a list of strings.  The way the parser works
// permits us to simply modify the first parameter, rather than copy
// the vector.

extern "C" String_list_ptr
script_string_list_push_back(String_list_ptr pv, const char* str, size_t len)
{
  if (pv == NULL)
    return script_new_string_list(str, len);
  else
    {
      pv->push_back(std::string(str, len));
      return pv;
    }
}

// Concatenate two string lists.  Either or both may be NULL.  The way
// the parser works permits us to modify the parameters, rather than
// copy the vector.

extern "C" String_list_ptr
script_string_list_append(String_list_ptr pv1, String_list_ptr pv2)
{
  if (pv1 == NULL)
    return pv2;
  if (pv2 == NULL)
    return pv1;
  pv1->insert(pv1->end(), pv2->begin(), pv2->end());
  return pv1;
}

// Add a new program header.

extern "C" void
script_add_phdr(void* closurev, const char* name, size_t namelen,
		unsigned int type, const Phdr_info* info)
{
  Parser_closure* closure = static_cast<Parser_closure*>(closurev);
  bool includes_filehdr = info->includes_filehdr != 0;
  bool includes_phdrs = info->includes_phdrs != 0;
  bool is_flags_valid = info->is_flags_valid != 0;
  Script_sections* ss = closure->script_options()->script_sections();
  ss->add_phdr(name, namelen, type, includes_filehdr, includes_phdrs,
	       is_flags_valid, info->flags, info->load_address);
  closure->clear_skip_on_incompatible_target();
}

// Convert a program header string to a type.

#define PHDR_TYPE(NAME) { #NAME, sizeof(#NAME) - 1, elfcpp::NAME }

static struct
{
  const char* name;
  size_t namelen;
  unsigned int val;
} phdr_type_names[] =
{
  PHDR_TYPE(PT_NULL),
  PHDR_TYPE(PT_LOAD),
  PHDR_TYPE(PT_DYNAMIC),
  PHDR_TYPE(PT_INTERP),
  PHDR_TYPE(PT_NOTE),
  PHDR_TYPE(PT_SHLIB),
  PHDR_TYPE(PT_PHDR),
  PHDR_TYPE(PT_TLS),
  PHDR_TYPE(PT_GNU_EH_FRAME),
  PHDR_TYPE(PT_GNU_STACK),
  PHDR_TYPE(PT_GNU_RELRO)
};

extern "C" unsigned int
script_phdr_string_to_type(void* closurev, const char* name, size_t namelen)
{
  for (unsigned int i = 0;
       i < sizeof(phdr_type_names) / sizeof(phdr_type_names[0]);
       ++i)
    if (namelen == phdr_type_names[i].namelen
	&& strncmp(name, phdr_type_names[i].name, namelen) == 0)
      return phdr_type_names[i].val;
  yyerror(closurev, _("unknown PHDR type (try integer)"));
  return elfcpp::PT_NULL;
}

extern "C" void
script_saw_segment_start_expression(void* closurev)
{
  Parser_closure* closure = static_cast<Parser_closure*>(closurev);
  Script_sections* ss = closure->script_options()->script_sections();
  ss->set_saw_segment_start_expression(true);
}

extern "C" void
script_set_section_region(void* closurev, const char* name, size_t namelen,
			  int set_vma)
{
  Parser_closure* closure = static_cast<Parser_closure*>(closurev);
  if (!closure->script_options()->saw_sections_clause())
    {
      gold_error(_("%s:%d:%d: MEMORY region '%.*s' referred to outside of "
		   "SECTIONS clause"),
		 closure->filename(), closure->lineno(), closure->charpos(),
		 static_cast<int>(namelen), name);
      return;
    }

  Script_sections* ss = closure->script_options()->script_sections();
  Memory_region* mr = ss->find_memory_region(name, namelen);
  if (mr == NULL)
    {
      gold_error(_("%s:%d:%d: MEMORY region '%.*s' not declared"),
		 closure->filename(), closure->lineno(), closure->charpos(),
		 static_cast<int>(namelen), name);
      return;
    }

  ss->set_memory_region(mr, set_vma);
}

extern "C" void
script_add_memory(void* closurev, const char* name, size_t namelen,
		  unsigned int attrs, Expression* origin, Expression* length)
{
  Parser_closure* closure = static_cast<Parser_closure*>(closurev);
  Script_sections* ss = closure->script_options()->script_sections();
  ss->add_memory_region(name, namelen, attrs, origin, length);
}

extern "C" unsigned int
script_parse_memory_attr(void* closurev, const char* attrs, size_t attrlen,
			 int invert)
{
  int attributes = 0;

  while (attrlen--)
    switch (*attrs++)
      {
      case 'R':
      case 'r':
	attributes |= MEM_READABLE; break;
      case 'W':
      case 'w':
	attributes |= MEM_READABLE | MEM_WRITEABLE; break;
      case 'X':
      case 'x':
	attributes |= MEM_EXECUTABLE; break;
      case 'A':
      case 'a':
	attributes |= MEM_ALLOCATABLE; break;
      case 'I':
      case 'i':
      case 'L':
      case 'l':
	attributes |= MEM_INITIALIZED; break;
      default:
	yyerror(closurev, _("unknown MEMORY attribute"));
      }

  if (invert)
    attributes = (~ attributes) & MEM_ATTR_MASK;

  return attributes;
}

extern "C" void
script_include_directive(void* closurev, const char*, size_t)
{
  // FIXME: Implement ?
  yyerror (closurev, _("GOLD does not currently support INCLUDE directives"));
}

// Functions for memory regions.

extern "C" Expression*
script_exp_function_origin(void* closurev, const char* name, size_t namelen)
{
  Parser_closure* closure = static_cast<Parser_closure*>(closurev);
  Script_sections* ss = closure->script_options()->script_sections();
  Expression* origin = ss->find_memory_region_origin(name, namelen);

  if (origin == NULL)
    {
      gold_error(_("undefined memory region '%s' referenced "
		   "in ORIGIN expression"),
		 name);
      // Create a dummy expression to prevent crashes later on.
      origin = script_exp_integer(0);
    }

  return origin;
}

extern "C" Expression*
script_exp_function_length(void* closurev, const char* name, size_t namelen)
{
  Parser_closure* closure = static_cast<Parser_closure*>(closurev);
  Script_sections* ss = closure->script_options()->script_sections();
  Expression* length = ss->find_memory_region_length(name, namelen);

  if (length == NULL)
    {
      gold_error(_("undefined memory region '%s' referenced "
		   "in LENGTH expression"),
		 name);
      // Create a dummy expression to prevent crashes later on.
      length = script_exp_integer(0);
    }

  return length;
}
