111
|
1 // import.h -- Go frontend import declarations. -*- C++ -*-
|
|
2
|
|
3 // Copyright 2009 The Go Authors. All rights reserved.
|
|
4 // Use of this source code is governed by a BSD-style
|
|
5 // license that can be found in the LICENSE file.
|
|
6
|
|
7 #ifndef GO_IMPORT_H
|
|
8 #define GO_IMPORT_H
|
|
9
|
|
10 #include "export.h"
|
|
11 #include "go-linemap.h"
|
|
12
|
|
13 class Gogo;
|
|
14 class Package;
|
|
15 class Type;
|
|
16 class Named_object;
|
|
17 class Named_type;
|
|
18 class Expression;
|
|
19
|
|
20 // This class manages importing Go declarations.
|
|
21
|
|
22 class Import
|
|
23 {
|
|
24 public:
|
|
25 // The Stream class is an interface used to read the data. The
|
|
26 // caller should instantiate a child of this class.
|
|
27 class Stream
|
|
28 {
|
|
29 public:
|
|
30 Stream();
|
|
31 virtual ~Stream();
|
|
32
|
|
33 // Return whether we have seen an error.
|
|
34 bool
|
|
35 saw_error() const
|
|
36 { return this->saw_error_; }
|
|
37
|
|
38 // Record that we've seen an error.
|
|
39 void
|
|
40 set_saw_error()
|
|
41 { this->saw_error_ = true; }
|
|
42
|
|
43 // Return the next character (a value from 0 to 0xff) without
|
|
44 // advancing. Returns -1 at end of stream.
|
|
45 int
|
|
46 peek_char();
|
|
47
|
|
48 // Look for LENGTH characters, setting *BYTES to point to them.
|
|
49 // Returns false if the bytes are not available. Does not
|
|
50 // advance.
|
|
51 bool
|
|
52 peek(size_t length, const char** bytes)
|
|
53 { return this->do_peek(length, bytes); }
|
|
54
|
|
55 // Return the next character (a value from 0 to 0xff) and advance
|
|
56 // the read position by 1. Returns -1 at end of stream.
|
|
57 int
|
|
58 get_char()
|
|
59 {
|
|
60 int c = this->peek_char();
|
|
61 this->advance(1);
|
|
62 return c;
|
|
63 }
|
|
64
|
|
65 // Return true if at the end of the stream.
|
|
66 bool
|
|
67 at_eof()
|
|
68 { return this->peek_char() == -1; }
|
|
69
|
|
70 // Return true if the next bytes match STR.
|
|
71 bool
|
|
72 match_c_string(const char* str)
|
|
73 { return this->match_bytes(str, strlen(str)); }
|
|
74
|
|
75 // Return true if the next LENGTH bytes match BYTES.
|
|
76 bool
|
|
77 match_bytes(const char* bytes, size_t length);
|
|
78
|
|
79 // Give an error if the next bytes do not match STR. Advance the
|
|
80 // read position by the length of STR.
|
|
81 void
|
|
82 require_c_string(Location location, const char* str)
|
|
83 { this->require_bytes(location, str, strlen(str)); }
|
|
84
|
|
85 // Given an error if the next LENGTH bytes do not match BYTES.
|
|
86 // Advance the read position by LENGTH.
|
|
87 void
|
|
88 require_bytes(Location, const char* bytes, size_t length);
|
|
89
|
|
90 // Advance the read position by SKIP bytes.
|
|
91 void
|
|
92 advance(size_t skip)
|
|
93 {
|
|
94 this->do_advance(skip);
|
|
95 this->pos_ += skip;
|
|
96 }
|
|
97
|
|
98 // Return the current read position. This returns int because it
|
|
99 // is more convenient in error reporting. FIXME.
|
|
100 int
|
|
101 pos()
|
|
102 { return static_cast<int>(this->pos_); }
|
|
103
|
|
104 protected:
|
|
105 // This function should set *BYTES to point to a buffer holding
|
|
106 // the LENGTH bytes at the current read position. It should
|
|
107 // return false if the bytes are not available. This should not
|
|
108 // change the current read position.
|
|
109 virtual bool
|
|
110 do_peek(size_t length, const char** bytes) = 0;
|
|
111
|
|
112 // This function should advance the current read position LENGTH
|
|
113 // bytes.
|
|
114 virtual void
|
|
115 do_advance(size_t skip) = 0;
|
|
116
|
|
117 private:
|
|
118 // The current read position.
|
|
119 size_t pos_;
|
|
120 // True if we've seen an error reading from this stream.
|
|
121 bool saw_error_;
|
|
122 };
|
|
123
|
|
124 // Find import data. This searches the file system for FILENAME and
|
|
125 // returns a pointer to a Stream object to read the data that it
|
|
126 // exports. LOCATION is the location of the import statement.
|
|
127 // RELATIVE_IMPORT_PATH is used as a prefix for a relative import.
|
|
128 static Stream*
|
|
129 open_package(const std::string& filename, Location location,
|
|
130 const std::string& relative_import_path);
|
|
131
|
|
132 // Constructor.
|
|
133 Import(Stream*, Location);
|
|
134
|
|
135 // Register the builtin types.
|
|
136 void
|
|
137 register_builtin_types(Gogo*);
|
|
138
|
|
139 // Import everything defined in the stream. LOCAL_NAME is the local
|
|
140 // name to be used for bindings; if it is the string "." then
|
|
141 // bindings should be inserted in the global scope. If LOCAL_NAME
|
|
142 // is the empty string then the name of the package itself is the
|
|
143 // local name. This returns the imported package, or NULL on error.
|
|
144 Package*
|
|
145 import(Gogo*, const std::string& local_name, bool is_local_name_exported);
|
|
146
|
|
147 // The location of the import statement.
|
|
148 Location
|
|
149 location() const
|
|
150 { return this->location_; }
|
|
151
|
|
152 // Return the package we are importing.
|
|
153 Package*
|
|
154 package() const
|
|
155 { return this->package_; }
|
|
156
|
|
157 // Return the next character.
|
|
158 int
|
|
159 peek_char()
|
|
160 { return this->stream_->peek_char(); }
|
|
161
|
|
162 // Return the next character and advance.
|
|
163 int
|
|
164 get_char()
|
|
165 { return this->stream_->get_char(); }
|
|
166
|
|
167 // Return true at the end of the stream.
|
|
168 bool
|
|
169 at_eof()
|
|
170 { return this->stream_->at_eof(); }
|
|
171
|
|
172 // Return whether the next bytes match STR.
|
|
173 bool
|
|
174 match_c_string(const char* str)
|
|
175 { return this->stream_->match_c_string(str); }
|
|
176
|
|
177 // Require that the next bytes match STR.
|
|
178 void
|
|
179 require_c_string(const char* str)
|
|
180 { this->stream_->require_c_string(this->location_, str); }
|
|
181
|
|
182 // Advance the stream SKIP bytes.
|
|
183 void
|
|
184 advance(size_t skip)
|
|
185 { this->stream_->advance(skip); }
|
|
186
|
|
187 // Read an identifier.
|
|
188 std::string
|
|
189 read_identifier();
|
|
190
|
|
191 // Read a name. This is like read_identifier, except that a "?" is
|
|
192 // returned as an empty string. This matches Export::write_name.
|
|
193 std::string
|
|
194 read_name();
|
|
195
|
|
196 // Read a type.
|
|
197 Type*
|
|
198 read_type();
|
|
199
|
|
200 // Read an escape note.
|
|
201 std::string
|
|
202 read_escape();
|
|
203
|
|
204 private:
|
|
205 static Stream*
|
|
206 try_package_in_directory(const std::string&, Location);
|
|
207
|
|
208 static int
|
|
209 try_suffixes(std::string*);
|
|
210
|
|
211 static Stream*
|
|
212 find_export_data(const std::string& filename, int fd, Location);
|
|
213
|
|
214 static Stream*
|
|
215 find_object_export_data(const std::string& filename, int fd,
|
|
216 off_t offset, Location);
|
|
217
|
|
218 static const int archive_magic_len = 8;
|
|
219
|
|
220 static bool
|
|
221 is_archive_magic(const char*);
|
|
222
|
|
223 static Stream*
|
|
224 find_archive_export_data(const std::string& filename, int fd,
|
|
225 Location);
|
|
226
|
|
227 // Read a package line.
|
|
228 void
|
|
229 read_one_package();
|
|
230
|
|
231 // Read an import line.
|
|
232 void
|
|
233 read_one_import();
|
|
234
|
|
235 // Read the import control functions and init graph.
|
|
236 void
|
|
237 read_import_init_fns(Gogo*);
|
|
238
|
|
239 // Import a constant.
|
|
240 void
|
|
241 import_const();
|
|
242
|
|
243 // Import a type.
|
|
244 void
|
|
245 import_type();
|
|
246
|
|
247 // Import a variable.
|
|
248 void
|
|
249 import_var();
|
|
250
|
|
251 // Import a function.
|
|
252 Named_object*
|
|
253 import_func(Package*);
|
|
254
|
|
255 // Register a single builtin type.
|
|
256 void
|
|
257 register_builtin_type(Gogo*, const char* name, Builtin_code);
|
|
258
|
|
259 // Get an integer from a string.
|
|
260 bool
|
|
261 string_to_int(const std::string&, bool is_neg_ok, int* ret);
|
|
262
|
|
263 // Get an unsigned integer from a string.
|
|
264 bool
|
|
265 string_to_unsigned(const std::string& s, unsigned* ret)
|
|
266 {
|
|
267 int ivalue;
|
|
268 if (!this->string_to_int(s, false, &ivalue))
|
|
269 return false;
|
|
270 *ret = static_cast<unsigned>(ivalue);
|
|
271 return true;
|
|
272 }
|
|
273
|
|
274 // Return the version number of the export data we're reading.
|
|
275 Export_data_version
|
|
276 version() const { return this->version_; }
|
|
277
|
|
278 // The general IR.
|
|
279 Gogo* gogo_;
|
|
280 // The stream from which to read import data.
|
|
281 Stream* stream_;
|
|
282 // The location of the import statement we are processing.
|
|
283 Location location_;
|
|
284 // The package we are importing.
|
|
285 Package* package_;
|
|
286 // Whether to add new objects to the global scope, rather than to a
|
|
287 // package scope.
|
|
288 bool add_to_globals_;
|
|
289 // Mapping from negated builtin type codes to Type structures.
|
|
290 std::vector<Named_type*> builtin_types_;
|
|
291 // Mapping from exported type codes to Type structures.
|
|
292 std::vector<Type*> types_;
|
|
293 // Version of export data we're reading.
|
|
294 Export_data_version version_;
|
|
295 };
|
|
296
|
|
297 // Read import data from a string.
|
|
298
|
|
299 class Stream_from_string : public Import::Stream
|
|
300 {
|
|
301 public:
|
|
302 Stream_from_string(const std::string& str)
|
|
303 : str_(str), pos_(0)
|
|
304 { }
|
|
305
|
|
306 protected:
|
|
307 bool
|
|
308 do_peek(size_t length, const char** bytes)
|
|
309 {
|
|
310 if (this->pos_ + length > this->str_.length())
|
|
311 return false;
|
|
312 *bytes = this->str_.data() + this->pos_;
|
|
313 return true;
|
|
314 }
|
|
315
|
|
316 void
|
|
317 do_advance(size_t len)
|
|
318 { this->pos_ += len; }
|
|
319
|
|
320 private:
|
|
321 // The string of data we are reading.
|
|
322 std::string str_;
|
|
323 // The current position within the string.
|
|
324 size_t pos_;
|
|
325 };
|
|
326
|
|
327 // Read import data from a buffer allocated using malloc.
|
|
328
|
|
329 class Stream_from_buffer : public Import::Stream
|
|
330 {
|
|
331 public:
|
|
332 Stream_from_buffer(char* buf, size_t length)
|
|
333 : buf_(buf), length_(length), pos_(0)
|
|
334 { }
|
|
335
|
|
336 ~Stream_from_buffer()
|
|
337 { free(this->buf_); }
|
|
338
|
|
339 protected:
|
|
340 bool
|
|
341 do_peek(size_t length, const char** bytes)
|
|
342 {
|
|
343 if (this->pos_ + length > this->length_)
|
|
344 return false;
|
|
345 *bytes = this->buf_ + this->pos_;
|
|
346 return true;
|
|
347 }
|
|
348
|
|
349 void
|
|
350 do_advance(size_t len)
|
|
351 { this->pos_ += len; }
|
|
352
|
|
353 private:
|
|
354 // The data we are reading.
|
|
355 char* buf_;
|
|
356 // The length of the buffer.
|
|
357 size_t length_;
|
|
358 // The current position within the buffer.
|
|
359 size_t pos_;
|
|
360 };
|
|
361
|
|
362 // Read import data from an open file descriptor.
|
|
363
|
|
364 class Stream_from_file : public Import::Stream
|
|
365 {
|
|
366 public:
|
|
367 Stream_from_file(int fd);
|
|
368
|
|
369 ~Stream_from_file();
|
|
370
|
|
371 protected:
|
|
372 bool
|
|
373 do_peek(size_t, const char**);
|
|
374
|
|
375 void
|
|
376 do_advance(size_t);
|
|
377
|
|
378 private:
|
|
379 // No copying.
|
|
380 Stream_from_file(const Stream_from_file&);
|
|
381 Stream_from_file& operator=(const Stream_from_file&);
|
|
382
|
|
383 // The file descriptor.
|
|
384 int fd_;
|
|
385 // Data read from the file.
|
|
386 std::string data_;
|
|
387 };
|
|
388
|
|
389 #endif // !defined(GO_IMPORT_H)
|