const std::string& prefix,
const std::string& pkgpath,
int package_priority,
+ const std::map<std::string, Package*>& packages,
const std::map<std::string, Package*>& imports,
const std::string& import_init_fn,
const std::set<Import_init>& imported_init_fns,
snprintf(buf, sizeof buf, "priority %d;\n", package_priority);
this->write_c_string(buf);
+ this->write_packages(packages);
+
this->write_imports(imports);
this->write_imported_init_fns(package_name, package_priority, import_init_fn,
this->stream_->write_checksum(s);
}
+// Sort packages.
+
+static bool
+packages_compare(const Package* a, const Package* b)
+{
+ return a->package_name() < b->package_name();
+}
+
+// Write out all the known packages whose pkgpath symbol is not a
+// simple transformation of the pkgpath, so that the importing code
+// can reliably know it.
+
+void
+Export::write_packages(const std::map<std::string, Package*>& packages)
+{
+ // Sort for consistent output.
+ std::vector<Package*> out;
+ for (std::map<std::string, Package*>::const_iterator p = packages.begin();
+ p != packages.end();
+ ++p)
+ {
+ if (p->second->pkgpath_symbol()
+ != Gogo::pkgpath_for_symbol(p->second->pkgpath()))
+ out.push_back(p->second);
+ }
+
+ std::sort(out.begin(), out.end(), packages_compare);
+
+ for (std::vector<Package*>::const_iterator p = out.begin();
+ p != out.end();
+ ++p)
+ {
+ this->write_c_string("package ");
+ this->write_string((*p)->package_name());
+ this->write_c_string(" ");
+ this->write_string((*p)->pkgpath());
+ this->write_c_string(" ");
+ this->write_string((*p)->pkgpath_symbol());
+ this->write_c_string(";\n");
+ }
+}
+
// Sort imported packages.
static bool
// PREFIX is the package prefix. PKGPATH is the package path.
// Only one of PREFIX and PKGPATH will be non-empty.
// PACKAGE_PRIORITY is the priority to use for this package.
+ // PACKAGES is all the packages we have seen.
// IMPORTS is the explicitly imported packages.
// IMPORT_INIT_FN is the name of the import initialization function
// for this package; it will be empty if none is needed.
const std::string& prefix,
const std::string& pkgpath,
int package_priority,
+ const std::map<std::string, Package*>& packages,
const std::map<std::string, Package*>& imports,
const std::string& import_init_fn,
const std::set<Import_init>& imported_init_fns,
Export(const Export&);
Export& operator=(const Export&);
+ // Write out all known packages.
+ void
+ write_packages(const std::map<std::string, Package*>& packages);
+
// Write out the imported packages.
void
write_imports(const std::map<std::string, Package*>& imports);
prefix,
pkgpath,
this->package_priority(),
+ this->packages_,
this->imports_,
(this->need_init_fn_ && !this->is_main_package()
? this->get_init_fn_name()
Package::pkgpath_symbol() const
{
if (this->pkgpath_symbol_.empty())
- {
- // In the general case, this is wrong, because the package might
- // have been compiled with -fprefix. However, it is what we
- // used to do, so it is no more wrong than we were before.
- return Gogo::pkgpath_for_symbol(this->pkgpath_);
- }
+ return Gogo::pkgpath_for_symbol(this->pkgpath_);
return this->pkgpath_symbol_;
}
this->package_->set_priority(prio);
this->require_c_string(";\n");
+ while (stream->match_c_string("package"))
+ this->read_one_package();
+
while (stream->match_c_string("import"))
this->read_one_import();
return this->package_;
}
+// Read a package line. This let us reliably determine the pkgpath
+// symbol, even if the package was compiled with a -fgo-prefix option.
+
+void
+Import::read_one_package()
+{
+ this->require_c_string("package ");
+ std::string package_name = this->read_identifier();
+ this->require_c_string(" ");
+ std::string pkgpath = this->read_identifier();
+ this->require_c_string(" ");
+ std::string pkgpath_symbol = this->read_identifier();
+ this->require_c_string(";\n");
+
+ Package* p = this->gogo_->register_package(pkgpath, pkgpath_symbol,
+ Linemap::unknown_location());
+ p->set_package_name(package_name, this->location());
+}
+
// Read an import line. We don't actually care about these.
void
find_archive_export_data(const std::string& filename, int fd,
Location);
+ // Read a package line.
+ void
+ read_one_package();
+
// Read an import line.
void
read_one_import();