Skip to content

Commit 92152c8

Browse files
compiler: support -fgo-importcfg
Change-Id: I2ca2554e683b51c1686f406d9f802ede50f9759f Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/506095 Reviewed-by: Than McIntosh <[email protected]> Reviewed-by: Cherry Mui <[email protected]>
1 parent 68a756b commit 92152c8

File tree

5 files changed

+162
-6
lines changed

5 files changed

+162
-6
lines changed

go/embed.cc

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@
1919

2020
// Read a file into *DATA. Returns false on error.
2121

22-
static bool
23-
read_file(const char* filename, Location loc, std::string* data)
22+
bool
23+
Gogo::read_file(const char* filename, Location loc, std::string* data)
2424
{
2525
int fd = open(filename, O_RDONLY | O_BINARY);
2626
if (fd < 0)
@@ -346,7 +346,8 @@ Gogo::read_embedcfg(const char *filename)
346346
bool
347347
Embedcfg_reader::initialize_from_file()
348348
{
349-
if (!read_file(this->filename_, Linemap::unknown_location(), &this->data_))
349+
if (!Gogo::read_file(this->filename_, Linemap::unknown_location(),
350+
&this->data_))
350351
return false;
351352
if (this->data_.empty())
352353
{
@@ -849,7 +850,7 @@ Gogo::initializer_for_embeds(Type* type,
849850
}
850851

851852
std::string data;
852-
if (!read_file(this->embed_files_[paths[0]].c_str(), loc, &data))
853+
if (!Gogo::read_file(this->embed_files_[paths[0]].c_str(), loc, &data))
853854
return Expression::make_error(loc);
854855

855856
Expression* e = Expression::make_string(data, loc);
@@ -909,7 +910,7 @@ Gogo::initializer_for_embeds(Type* type,
909910
std::string data;
910911
if ((*pp)[pp->size() - 1] != '/')
911912
{
912-
if (!read_file(this->embed_files_[*pp].c_str(), loc, &data))
913+
if (!Gogo::read_file(this->embed_files_[*pp].c_str(), loc, &data))
913914
return Expression::make_error(loc);
914915
}
915916

go/go.cc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ go_create_gogo(const struct go_create_gogo_args* args)
4040
::gogo->set_compiling_runtime(args->compiling_runtime);
4141
if (args->c_header != NULL)
4242
::gogo->set_c_header(args->c_header);
43+
if (args->importcfg != NULL)
44+
::gogo->read_importcfg(args->importcfg);
4345
if (args->embedcfg != NULL)
4446
::gogo->read_embedcfg(args->embedcfg);
4547
::gogo->set_debug_escape_level(args->debug_escape_level);

go/gogo.cc

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,10 @@ Gogo::Gogo(Backend* backend, Linemap* linemap, int, int pointer_size)
5252
prefix_from_option_(false),
5353
relative_import_path_(),
5454
c_header_(),
55+
import_map_(),
56+
package_file_(),
57+
embed_patterns_(),
58+
embed_files_(),
5559
check_divide_by_zero_(true),
5660
check_divide_overflow_(true),
5761
compiling_runtime_(false),
@@ -517,7 +521,20 @@ Gogo::import_package(const std::string& filename,
517521
return;
518522
}
519523

520-
Import::Stream* stream = Import::open_package(filename, location,
524+
// If we are using an importcfg file we have to check two mappings.
525+
// IMPORT_MAP_ is a mapping from package path to real package path,
526+
// for vendoring. PACKAGE_FILE_ is a mapping from package path to
527+
// file name, to find the file in the build cache.
528+
std::string path = filename;
529+
Unordered_map(std::string, std::string)::const_iterator pi;
530+
pi = this->import_map_.find(filename);
531+
if (pi != this->import_map_.end())
532+
path = pi->second;
533+
pi = this->package_file_.find(path);
534+
if (pi != this->package_file_.end())
535+
path = pi->second;
536+
537+
Import::Stream* stream = Import::open_package(path, location,
521538
this->relative_import_path_);
522539
if (stream == NULL)
523540
{

go/gogo.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -393,6 +393,10 @@ class Gogo
393393
set_c_header(const std::string& s)
394394
{ this->c_header_ = s; }
395395

396+
// Read an importcfg file.
397+
void
398+
read_importcfg(const char* filename);
399+
396400
// Read an embedcfg file.
397401
void
398402
read_embedcfg(const char* filename);
@@ -1126,6 +1130,10 @@ class Gogo
11261130
static size_t
11271131
special_name_pos(const std::string& name);
11281132

1133+
// Read a file into memory.
1134+
static bool
1135+
read_file(const char* filename, Location loc, std::string* data);
1136+
11291137
private:
11301138
// During parsing, we keep a stack of functions. Each function on
11311139
// the stack is one that we are currently parsing. For each
@@ -1295,6 +1303,10 @@ class Gogo
12951303
std::string relative_import_path_;
12961304
// The C header file to write, from the -fgo-c-header option.
12971305
std::string c_header_;
1306+
// Mapping from imports in the source file to the real import paths.
1307+
Unordered_map(std::string, std::string) import_map_;
1308+
// Mapping from import paths to files to read.
1309+
Unordered_map(std::string, std::string) package_file_;
12981310
// Patterns from an embedcfg file.
12991311
Embed_patterns embed_patterns_;
13001312
// Mapping from file to full path from an embedcfg file.

go/import.cc

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,130 @@ go_add_search_path(const char* path)
3434
search_path.push_back(std::string(path));
3535
}
3636

37+
// Read an importcfg file.
38+
39+
void
40+
Gogo::read_importcfg(const char* filename)
41+
{
42+
std::string data;
43+
if (!Gogo::read_file(filename, Linemap::unknown_location(), &data))
44+
return;
45+
const char* p = data.data();
46+
const char* pend = p + data.length();
47+
int lineno = 0;
48+
const char *pnext = NULL;
49+
for (; p < pend; p = pnext)
50+
{
51+
// Line numbers start at 1.
52+
lineno++;
53+
54+
// Find end of line.
55+
const char* pnl = static_cast<const char*>(memchr(p, '\n', pend - p));
56+
if (pnl != NULL)
57+
pnext = pnl + 1;
58+
else
59+
{
60+
pnl = pend;
61+
pnext = pnl;
62+
}
63+
64+
// Trim leading spaces.
65+
while (p < pnl)
66+
{
67+
unsigned int rune;
68+
int rune_len = Lex::fetch_char(p, &rune);
69+
if (rune_len == 0)
70+
{
71+
go_error_at(Linemap::unknown_location(),
72+
"%s:%d: invalid character in importcfg file",
73+
filename, lineno);
74+
return;
75+
}
76+
if (!Lex::is_unicode_space(rune))
77+
break;
78+
p += rune_len;
79+
}
80+
81+
// Trim trailing spaces.
82+
while (pnl > p)
83+
{
84+
size_t start = pnl - p - 1;
85+
unsigned int rune = (unsigned char)p[start];
86+
int rune_len = 1;
87+
if (rune > 0x7f)
88+
{
89+
for (start--; start > 0; start--)
90+
{
91+
unsigned char c = p[start];
92+
if ((c & 0xc0) != 0x80)
93+
break;
94+
}
95+
rune_len = Lex::fetch_char(p + start, &rune);
96+
if (static_cast<size_t>(rune_len) != (pnl - p) - start)
97+
{
98+
go_error_at(Linemap::unknown_location(),
99+
"%s:%d: invalid character in importcfg file",
100+
filename, lineno);
101+
return;
102+
}
103+
}
104+
if (!Lex::is_unicode_space(rune))
105+
break;
106+
pnl -= rune_len;
107+
}
108+
109+
// Skip empty lines and comment lines.
110+
if (p == pnl || *p == '#')
111+
continue;
112+
113+
size_t verb_len;
114+
const char* psp = static_cast<const char*>(memchr(p, ' ', pnl - p));
115+
if (psp == NULL)
116+
verb_len = pnl - p;
117+
else
118+
verb_len = psp - p;
119+
120+
bool importmap = false;
121+
bool packagefile = false;
122+
if (strncmp(p, "importmap", verb_len) == 0)
123+
importmap = true;
124+
else if (strncmp(p, "packagefile", verb_len) == 0)
125+
packagefile = true;
126+
else
127+
{
128+
go_error_at(Linemap::unknown_location(),
129+
"%s:%d: unknown directive in importcfg file",
130+
filename, lineno);
131+
return;
132+
}
133+
134+
const char* peq;
135+
if (psp == NULL)
136+
peq = NULL;
137+
else
138+
{
139+
psp++;
140+
peq = static_cast<const char*>(memchr(psp, '=', pnl - psp));
141+
}
142+
if (peq == NULL || peq + 1 == pnl)
143+
{
144+
go_error_at(Linemap::unknown_location(),
145+
"%s:%d: invalid syntax in importcfg file",
146+
filename, lineno);
147+
return;
148+
}
149+
150+
std::string first(psp, peq - psp);
151+
std::string second(peq + 1, pnl - (peq + 1));
152+
if (importmap)
153+
this->import_map_[first] = second;
154+
else if (packagefile)
155+
this->package_file_[first] = second;
156+
else
157+
go_unreachable();
158+
}
159+
}
160+
37161
// Find import data. This searches the file system for FILENAME and
38162
// returns a pointer to a Stream object to read the data that it
39163
// exports. If the file is not found, it returns NULL.

0 commit comments

Comments
 (0)