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

// Copyright 2006, 2007, 2008, 2009, 2010, 2011 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;

 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_;
};

// Return the value of a TOKEN_INTEGER.

uint64_t
Token::integer_value() const
{
  gold_assert(this->classification_ == TOKEN_INTEGER);

  size_t len = this->value_length_;

  uint64_t multiplier = 1;
  char last = this->value_[len - 1];
  if (last == 'm' || last == 'M')
    {
      multiplier = 1024 * 1024;
      --len;
    }
  else if (last == 'k' || last == 'K')
    {
      multiplier = 1024;
      --len;
    }

  char *end;
  uint64_t ret = strtoull(this->value_, &end, 0);
  gold_assert(static_cast<size_t>(end - this->value_) == len);

  return ret * multiplier;
}

// 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.

// 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)) != NULL)
    match = new_match;

  // A special case: integers may be followed by a single M or K,
  // case-insensitive.
  if (classification == Token::TOKEN_INTEGER
      && (*match == 'm' || *match == 'M' || *match == 'k' || *match == 'K'))
    ++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,
		 Script_info* script_info)
    : 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),
      script_info_(script_info)
  {
    // 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();
  }

  // Return a pointer to the incremental info.
  Script_info*
  script_info()
  { return this->script_info_; }

 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_;
  // Pointer to incremental linking info.
  Script_info* script_info_;
};

// 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);

  Script_info* script_info = NULL;
  if (layout->incremental_inputs() != NULL)
    {
      const std::string& filename = input_file->filename();
      Timespec mtime = input_file->file().get_mtime();
      unsigned int arg_serial = input_argument->file().arg_serial();
      script_info = new Script_info(filename);
      layout->incremental_inputs()->report_script(script_info, arg_serial,
						  mtime);
    }

  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(),
			 script_info);

  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;
    }

  *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,
			 NULL);
  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, NULL);

  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)
{
  Parser_closure* closure = static_cast<Parser_closure*>(closurev);
  closure->script_options()->add_symbol_reference(name, length);
}

// 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());
  Input_argument& arg = closure->inputs()->add_file(file);
  arg.set_script_info(closure->script_info());
}

// 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());
  Input_argument& arg = closure->inputs()->add_file(file);
  arg.set_script_info(closure->script_info());
}

// 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_bfd_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;
}
