+
+/* 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);
+ 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);
+ gold_assert(tag != NULL);
+ tree->dependencies = deps;
+ 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.
+// TODO: In the old linker, the last argument used to be a bool, but I
+// don't know what it meant.
+
+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);
+ closure->push_language(std::string(lang, langlen));
+}
+
+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();
+}
+
+// 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);
+}
+
+// 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)
+{
+ 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)
+{
+ 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;
+}