mirror of
https://gcc.gnu.org/git/gcc.git
synced 2024-11-23 02:44:18 +08:00
compiler: support -fgo-importcfg
* lang.opt (fgo-importcfg): New option. * go-c.h (struct go_create_gogo_args): Add importcfg field. * go-lang.cc (go_importcfg): New static variable. (go_langhook_init): Set args.importcfg. (go_langhook_handle_option): Handle -fgo-importcfg. * gccgo.texi (Invoking gccgo): Document -fgo-importcfg. Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/506095
This commit is contained in:
parent
79d8fbbcbf
commit
3a39a31b8a
@ -271,6 +271,14 @@ pattern to a list of file names, and @code{Files} maps each file name
|
||||
to a full path to the file. This option is intended for use by the
|
||||
@command{go} command to implement @code{//go:embed}.
|
||||
|
||||
@cindex @option{-fgo-importcfg}
|
||||
@item -fgo-importcfg=@var{file}
|
||||
Identify a file that provides mappings for import package paths found
|
||||
in the Go source files. The file can contain two commands:
|
||||
@code{importpath} to rename import paths for vendoring and
|
||||
@code{packagefile} to map from package path to files containing export
|
||||
data. This option is intended for use by the @command{go} command.
|
||||
|
||||
@cindex @option{-g for gccgo}
|
||||
@item -g
|
||||
This is the standard @command{gcc} option (@pxref{Debugging Options, ,
|
||||
|
@ -41,6 +41,7 @@ struct go_create_gogo_args
|
||||
const char* prefix;
|
||||
const char* relative_import_path;
|
||||
const char* c_header;
|
||||
const char* importcfg;
|
||||
const char* embedcfg;
|
||||
Backend* backend;
|
||||
Linemap* linemap;
|
||||
|
@ -90,6 +90,7 @@ static const char *go_prefix = NULL;
|
||||
static const char *go_relative_import_path = NULL;
|
||||
static const char *go_c_header = NULL;
|
||||
static const char *go_embedcfg = NULL;
|
||||
static const char *go_importcfg = NULL;
|
||||
|
||||
/* Language hooks. */
|
||||
|
||||
@ -111,6 +112,7 @@ go_langhook_init (void)
|
||||
args.relative_import_path = go_relative_import_path;
|
||||
args.c_header = go_c_header;
|
||||
args.embedcfg = go_embedcfg;
|
||||
args.importcfg = go_importcfg;
|
||||
args.check_divide_by_zero = go_check_divide_zero;
|
||||
args.check_divide_overflow = go_check_divide_overflow;
|
||||
args.compiling_runtime = go_compiling_runtime;
|
||||
@ -286,6 +288,10 @@ go_langhook_handle_option (
|
||||
go_embedcfg = arg;
|
||||
break;
|
||||
|
||||
case OPT_fgo_importcfg_:
|
||||
go_importcfg = arg;
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Just return 1 to indicate that the option is valid. */
|
||||
break;
|
||||
|
@ -1,4 +1,4 @@
|
||||
68a756b6aadc901534cfddddad2b1e73fae9e34f
|
||||
92152c88ea8e2dd9e8c67e91bf4ae5e3edf1b506
|
||||
|
||||
The first line of this file holds the git revision number of the last
|
||||
merge done from the gofrontend repository.
|
||||
|
@ -19,8 +19,8 @@
|
||||
|
||||
// Read a file into *DATA. Returns false on error.
|
||||
|
||||
static bool
|
||||
read_file(const char* filename, Location loc, std::string* data)
|
||||
bool
|
||||
Gogo::read_file(const char* filename, Location loc, std::string* data)
|
||||
{
|
||||
int fd = open(filename, O_RDONLY | O_BINARY);
|
||||
if (fd < 0)
|
||||
@ -346,7 +346,8 @@ Gogo::read_embedcfg(const char *filename)
|
||||
bool
|
||||
Embedcfg_reader::initialize_from_file()
|
||||
{
|
||||
if (!read_file(this->filename_, Linemap::unknown_location(), &this->data_))
|
||||
if (!Gogo::read_file(this->filename_, Linemap::unknown_location(),
|
||||
&this->data_))
|
||||
return false;
|
||||
if (this->data_.empty())
|
||||
{
|
||||
@ -849,7 +850,7 @@ Gogo::initializer_for_embeds(Type* type,
|
||||
}
|
||||
|
||||
std::string data;
|
||||
if (!read_file(this->embed_files_[paths[0]].c_str(), loc, &data))
|
||||
if (!Gogo::read_file(this->embed_files_[paths[0]].c_str(), loc, &data))
|
||||
return Expression::make_error(loc);
|
||||
|
||||
Expression* e = Expression::make_string(data, loc);
|
||||
@ -909,7 +910,7 @@ Gogo::initializer_for_embeds(Type* type,
|
||||
std::string data;
|
||||
if ((*pp)[pp->size() - 1] != '/')
|
||||
{
|
||||
if (!read_file(this->embed_files_[*pp].c_str(), loc, &data))
|
||||
if (!Gogo::read_file(this->embed_files_[*pp].c_str(), loc, &data))
|
||||
return Expression::make_error(loc);
|
||||
}
|
||||
|
||||
|
@ -40,6 +40,8 @@ go_create_gogo(const struct go_create_gogo_args* args)
|
||||
::gogo->set_compiling_runtime(args->compiling_runtime);
|
||||
if (args->c_header != NULL)
|
||||
::gogo->set_c_header(args->c_header);
|
||||
if (args->importcfg != NULL)
|
||||
::gogo->read_importcfg(args->importcfg);
|
||||
if (args->embedcfg != NULL)
|
||||
::gogo->read_embedcfg(args->embedcfg);
|
||||
::gogo->set_debug_escape_level(args->debug_escape_level);
|
||||
|
@ -52,6 +52,10 @@ Gogo::Gogo(Backend* backend, Linemap* linemap, int, int pointer_size)
|
||||
prefix_from_option_(false),
|
||||
relative_import_path_(),
|
||||
c_header_(),
|
||||
import_map_(),
|
||||
package_file_(),
|
||||
embed_patterns_(),
|
||||
embed_files_(),
|
||||
check_divide_by_zero_(true),
|
||||
check_divide_overflow_(true),
|
||||
compiling_runtime_(false),
|
||||
@ -517,7 +521,20 @@ Gogo::import_package(const std::string& filename,
|
||||
return;
|
||||
}
|
||||
|
||||
Import::Stream* stream = Import::open_package(filename, location,
|
||||
// If we are using an importcfg file we have to check two mappings.
|
||||
// IMPORT_MAP_ is a mapping from package path to real package path,
|
||||
// for vendoring. PACKAGE_FILE_ is a mapping from package path to
|
||||
// file name, to find the file in the build cache.
|
||||
std::string path = filename;
|
||||
Unordered_map(std::string, std::string)::const_iterator pi;
|
||||
pi = this->import_map_.find(filename);
|
||||
if (pi != this->import_map_.end())
|
||||
path = pi->second;
|
||||
pi = this->package_file_.find(path);
|
||||
if (pi != this->package_file_.end())
|
||||
path = pi->second;
|
||||
|
||||
Import::Stream* stream = Import::open_package(path, location,
|
||||
this->relative_import_path_);
|
||||
if (stream == NULL)
|
||||
{
|
||||
|
@ -393,6 +393,10 @@ class Gogo
|
||||
set_c_header(const std::string& s)
|
||||
{ this->c_header_ = s; }
|
||||
|
||||
// Read an importcfg file.
|
||||
void
|
||||
read_importcfg(const char* filename);
|
||||
|
||||
// Read an embedcfg file.
|
||||
void
|
||||
read_embedcfg(const char* filename);
|
||||
@ -1126,6 +1130,10 @@ class Gogo
|
||||
static size_t
|
||||
special_name_pos(const std::string& name);
|
||||
|
||||
// Read a file into memory.
|
||||
static bool
|
||||
read_file(const char* filename, Location loc, std::string* data);
|
||||
|
||||
private:
|
||||
// During parsing, we keep a stack of functions. Each function on
|
||||
// the stack is one that we are currently parsing. For each
|
||||
@ -1295,6 +1303,10 @@ class Gogo
|
||||
std::string relative_import_path_;
|
||||
// The C header file to write, from the -fgo-c-header option.
|
||||
std::string c_header_;
|
||||
// Mapping from imports in the source file to the real import paths.
|
||||
Unordered_map(std::string, std::string) import_map_;
|
||||
// Mapping from import paths to files to read.
|
||||
Unordered_map(std::string, std::string) package_file_;
|
||||
// Patterns from an embedcfg file.
|
||||
Embed_patterns embed_patterns_;
|
||||
// Mapping from file to full path from an embedcfg file.
|
||||
|
@ -34,6 +34,130 @@ go_add_search_path(const char* path)
|
||||
search_path.push_back(std::string(path));
|
||||
}
|
||||
|
||||
// Read an importcfg file.
|
||||
|
||||
void
|
||||
Gogo::read_importcfg(const char* filename)
|
||||
{
|
||||
std::string data;
|
||||
if (!Gogo::read_file(filename, Linemap::unknown_location(), &data))
|
||||
return;
|
||||
const char* p = data.data();
|
||||
const char* pend = p + data.length();
|
||||
int lineno = 0;
|
||||
const char *pnext = NULL;
|
||||
for (; p < pend; p = pnext)
|
||||
{
|
||||
// Line numbers start at 1.
|
||||
lineno++;
|
||||
|
||||
// Find end of line.
|
||||
const char* pnl = static_cast<const char*>(memchr(p, '\n', pend - p));
|
||||
if (pnl != NULL)
|
||||
pnext = pnl + 1;
|
||||
else
|
||||
{
|
||||
pnl = pend;
|
||||
pnext = pnl;
|
||||
}
|
||||
|
||||
// Trim leading spaces.
|
||||
while (p < pnl)
|
||||
{
|
||||
unsigned int rune;
|
||||
int rune_len = Lex::fetch_char(p, &rune);
|
||||
if (rune_len == 0)
|
||||
{
|
||||
go_error_at(Linemap::unknown_location(),
|
||||
"%s:%d: invalid character in importcfg file",
|
||||
filename, lineno);
|
||||
return;
|
||||
}
|
||||
if (!Lex::is_unicode_space(rune))
|
||||
break;
|
||||
p += rune_len;
|
||||
}
|
||||
|
||||
// Trim trailing spaces.
|
||||
while (pnl > p)
|
||||
{
|
||||
size_t start = pnl - p - 1;
|
||||
unsigned int rune = (unsigned char)p[start];
|
||||
int rune_len = 1;
|
||||
if (rune > 0x7f)
|
||||
{
|
||||
for (start--; start > 0; start--)
|
||||
{
|
||||
unsigned char c = p[start];
|
||||
if ((c & 0xc0) != 0x80)
|
||||
break;
|
||||
}
|
||||
rune_len = Lex::fetch_char(p + start, &rune);
|
||||
if (static_cast<size_t>(rune_len) != (pnl - p) - start)
|
||||
{
|
||||
go_error_at(Linemap::unknown_location(),
|
||||
"%s:%d: invalid character in importcfg file",
|
||||
filename, lineno);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (!Lex::is_unicode_space(rune))
|
||||
break;
|
||||
pnl -= rune_len;
|
||||
}
|
||||
|
||||
// Skip empty lines and comment lines.
|
||||
if (p == pnl || *p == '#')
|
||||
continue;
|
||||
|
||||
size_t verb_len;
|
||||
const char* psp = static_cast<const char*>(memchr(p, ' ', pnl - p));
|
||||
if (psp == NULL)
|
||||
verb_len = pnl - p;
|
||||
else
|
||||
verb_len = psp - p;
|
||||
|
||||
bool importmap = false;
|
||||
bool packagefile = false;
|
||||
if (strncmp(p, "importmap", verb_len) == 0)
|
||||
importmap = true;
|
||||
else if (strncmp(p, "packagefile", verb_len) == 0)
|
||||
packagefile = true;
|
||||
else
|
||||
{
|
||||
go_error_at(Linemap::unknown_location(),
|
||||
"%s:%d: unknown directive in importcfg file",
|
||||
filename, lineno);
|
||||
return;
|
||||
}
|
||||
|
||||
const char* peq;
|
||||
if (psp == NULL)
|
||||
peq = NULL;
|
||||
else
|
||||
{
|
||||
psp++;
|
||||
peq = static_cast<const char*>(memchr(psp, '=', pnl - psp));
|
||||
}
|
||||
if (peq == NULL || peq + 1 == pnl)
|
||||
{
|
||||
go_error_at(Linemap::unknown_location(),
|
||||
"%s:%d: invalid syntax in importcfg file",
|
||||
filename, lineno);
|
||||
return;
|
||||
}
|
||||
|
||||
std::string first(psp, peq - psp);
|
||||
std::string second(peq + 1, pnl - (peq + 1));
|
||||
if (importmap)
|
||||
this->import_map_[first] = second;
|
||||
else if (packagefile)
|
||||
this->package_file_[first] = second;
|
||||
else
|
||||
go_unreachable();
|
||||
}
|
||||
}
|
||||
|
||||
// Find import data. This searches the file system for FILENAME and
|
||||
// returns a pointer to a Stream object to read the data that it
|
||||
// exports. If the file is not found, it returns NULL.
|
||||
|
@ -61,6 +61,10 @@ fgo-embedcfg=
|
||||
Go Joined RejectNegative
|
||||
-fgo-embedcfg=<file> List embedded files via go:embed.
|
||||
|
||||
fgo-importcfg=
|
||||
Go Joined RejectNegative
|
||||
-fgo-importcfg=<file> Provide file that tells where to find imports.
|
||||
|
||||
fgo-optimize-
|
||||
Go Joined
|
||||
-fgo-optimize-<type> Turn on optimization passes in the frontend.
|
||||
|
Loading…
Reference in New Issue
Block a user