Mercurial > projects > ldc
annotate dmd/module.c @ 837:331a176c1f4f
Removed error on naked, not fully complete, but I'll be doing more work on it during this Christmas, and some things do work.
Fixed taking delegate of final class method. see mini/delegate3.d.
author | Tomas Lindquist Olsen <tomas.l.olsen@gmail.com> |
---|---|
date | Tue, 09 Dec 2008 14:07:30 +0100 |
parents | dc8b8b7ea0c1 |
children | aa953cc960b6 |
rev | line source |
---|---|
336 | 1 |
2 // Compiler implementation of the D programming language | |
3 // Copyright (c) 1999-2007 by Digital Mars | |
4 // All Rights Reserved | |
5 // written by Walter Bright | |
6 // http://www.digitalmars.com | |
7 // License for redistribution is by either the Artistic License | |
8 // in artistic.txt, or the GNU General Public License in gnu.txt. | |
9 // See the included readme.txt for details. | |
10 | |
11 #include <stdio.h> | |
12 #include <stdlib.h> | |
13 #include <assert.h> | |
14 | |
15 #if _MSC_VER || __MINGW32__ | |
16 #include <malloc.h> | |
17 #endif | |
18 | |
19 #if IN_GCC | |
20 #include "gdc_alloca.h" | |
21 #endif | |
22 | |
23 #include "mem.h" | |
24 | |
25 #include "mars.h" | |
26 #include "module.h" | |
27 #include "parse.h" | |
28 #include "scope.h" | |
29 #include "identifier.h" | |
30 #include "id.h" | |
31 #include "import.h" | |
32 #include "dsymbol.h" | |
33 #include "hdrgen.h" | |
34 #include "lexer.h" | |
35 | |
36 #define MARS 1 | |
37 #include "html.h" | |
38 | |
39 #ifdef IN_GCC | |
40 #include "d-dmd-gcc.h" | |
41 #endif | |
42 | |
43 ClassDeclaration *Module::moduleinfo; | |
44 | |
45 Module *Module::rootModule; | |
46 DsymbolTable *Module::modules; | |
47 Array Module::amodules; | |
48 | |
49 Array Module::deferred; // deferred Dsymbol's needing semantic() run on them | |
50 unsigned Module::dprogress; | |
51 | |
52 void Module::init() | |
53 { | |
54 modules = new DsymbolTable(); | |
55 } | |
56 | |
57 Module::Module(char *filename, Identifier *ident, int doDocComment, int doHdrGen) | |
58 : Package(ident) | |
59 { | |
60 FileName *srcfilename; | |
61 | |
62 // printf("Module::Module(filename = '%s', ident = '%s')\n", filename, ident->toChars()); | |
63 this->arg = filename; | |
64 md = NULL; | |
65 errors = 0; | |
66 numlines = 0; | |
67 members = NULL; | |
68 isHtml = 0; | |
69 isDocFile = 0; | |
70 needmoduleinfo = 0; | |
71 #ifdef IN_GCC | |
72 strictlyneedmoduleinfo = 0; | |
73 #endif | |
74 insearch = 0; | |
75 searchCacheIdent = NULL; | |
76 searchCacheSymbol = NULL; | |
77 searchCacheFlags = 0; | |
78 semanticstarted = 0; | |
79 semanticdone = 0; | |
80 decldefs = NULL; | |
81 vmoduleinfo = NULL; | |
82 massert = NULL; | |
83 marray = NULL; | |
84 sictor = NULL; | |
85 sctor = NULL; | |
86 sdtor = NULL; | |
87 stest = NULL; | |
88 sfilename = NULL; | |
89 root = 0; | |
90 importedFrom = NULL; | |
91 srcfile = NULL; | |
580
7824c21a58e3
Restructure path handling a bit. Fixes #66.
Christian Kamm <kamm incasoftware de>
parents:
550
diff
changeset
|
92 objfile = NULL; |
336 | 93 docfile = NULL; |
580
7824c21a58e3
Restructure path handling a bit. Fixes #66.
Christian Kamm <kamm incasoftware de>
parents:
550
diff
changeset
|
94 hdrfile = NULL; |
336 | 95 |
96 debuglevel = 0; | |
97 debugids = NULL; | |
98 debugidsNot = NULL; | |
99 versionlevel = 0; | |
100 versionids = NULL; | |
101 versionidsNot = NULL; | |
102 | |
103 macrotable = NULL; | |
104 escapetable = NULL; | |
105 doppelganger = 0; | |
106 cov = NULL; | |
107 covb = NULL; | |
108 | |
109 srcfilename = FileName::defaultExt(filename, global.mars_ext); | |
110 if (!srcfilename->equalsExt(global.mars_ext) && | |
510
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
111 !srcfilename->equalsExt(global.hdr_ext) && |
336 | 112 !srcfilename->equalsExt("dd")) |
113 { | |
114 if (srcfilename->equalsExt("html") || | |
115 srcfilename->equalsExt("htm") || | |
116 srcfilename->equalsExt("xhtml")) | |
117 isHtml = 1; | |
118 else | |
119 { error("source file name '%s' must have .%s extension", srcfilename->toChars(), global.mars_ext); | |
120 fatal(); | |
121 } | |
122 } | |
123 srcfile = new File(srcfilename); | |
124 | |
664
eef8ac26c66c
Some missed LLVMDC -> LDC.
Christian Kamm <kamm incasoftware de>
parents:
643
diff
changeset
|
125 // LDC |
486
a34078905d01
Added pragma(llvmdc, "string") for misc per-module compiler configuration, currently "string" can only be "verbose" which forces -vv for module it appears in.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
336
diff
changeset
|
126 llvmForceLogging = false; |
604
a30fc28e8f23
Make creating and deleting of doc and hdr files dependent on whether doc and
Christian Kamm <kamm incasoftware de>
parents:
598
diff
changeset
|
127 this->doDocComment = doDocComment; |
a30fc28e8f23
Make creating and deleting of doc and hdr files dependent on whether doc and
Christian Kamm <kamm incasoftware de>
parents:
598
diff
changeset
|
128 this->doHdrGen = doHdrGen; |
336 | 129 } |
130 | |
580
7824c21a58e3
Restructure path handling a bit. Fixes #66.
Christian Kamm <kamm incasoftware de>
parents:
550
diff
changeset
|
131 File* Module::buildFilePath(char* forcename, char* path, char* ext) |
336 | 132 { |
580
7824c21a58e3
Restructure path handling a bit. Fixes #66.
Christian Kamm <kamm incasoftware de>
parents:
550
diff
changeset
|
133 char *argobj; |
7824c21a58e3
Restructure path handling a bit. Fixes #66.
Christian Kamm <kamm incasoftware de>
parents:
550
diff
changeset
|
134 if (forcename) |
7824c21a58e3
Restructure path handling a bit. Fixes #66.
Christian Kamm <kamm incasoftware de>
parents:
550
diff
changeset
|
135 argobj = forcename; |
336 | 136 else |
580
7824c21a58e3
Restructure path handling a bit. Fixes #66.
Christian Kamm <kamm incasoftware de>
parents:
550
diff
changeset
|
137 { |
7824c21a58e3
Restructure path handling a bit. Fixes #66.
Christian Kamm <kamm incasoftware de>
parents:
550
diff
changeset
|
138 if (global.params.preservePaths) |
7824c21a58e3
Restructure path handling a bit. Fixes #66.
Christian Kamm <kamm incasoftware de>
parents:
550
diff
changeset
|
139 argobj = (char*)this->arg; |
7824c21a58e3
Restructure path handling a bit. Fixes #66.
Christian Kamm <kamm incasoftware de>
parents:
550
diff
changeset
|
140 else |
7824c21a58e3
Restructure path handling a bit. Fixes #66.
Christian Kamm <kamm incasoftware de>
parents:
550
diff
changeset
|
141 argobj = FileName::name((char*)this->arg); |
336 | 142 |
580
7824c21a58e3
Restructure path handling a bit. Fixes #66.
Christian Kamm <kamm incasoftware de>
parents:
550
diff
changeset
|
143 if (global.params.fqnNames) |
643 | 144 { |
580
7824c21a58e3
Restructure path handling a bit. Fixes #66.
Christian Kamm <kamm incasoftware de>
parents:
550
diff
changeset
|
145 if(md) |
7824c21a58e3
Restructure path handling a bit. Fixes #66.
Christian Kamm <kamm incasoftware de>
parents:
550
diff
changeset
|
146 argobj = FileName::replaceName(argobj, md->toChars()); |
7824c21a58e3
Restructure path handling a bit. Fixes #66.
Christian Kamm <kamm incasoftware de>
parents:
550
diff
changeset
|
147 else |
7824c21a58e3
Restructure path handling a bit. Fixes #66.
Christian Kamm <kamm incasoftware de>
parents:
550
diff
changeset
|
148 argobj = FileName::replaceName(argobj, toChars()); |
7824c21a58e3
Restructure path handling a bit. Fixes #66.
Christian Kamm <kamm incasoftware de>
parents:
550
diff
changeset
|
149 |
643 | 150 // add ext, otherwise forceExt will make nested.module into nested.bc |
151 size_t len = strlen(argobj); | |
152 size_t extlen = strlen(ext); | |
153 char* s = (char *)alloca(len + 1 + extlen + 1); | |
154 memcpy(s, argobj, len); | |
155 s[len] = '.'; | |
156 memcpy(s + len + 1, ext, extlen + 1); | |
157 s[len+1+extlen] = 0; | |
158 argobj = s; | |
159 } | |
336 | 160 } |
161 | |
580
7824c21a58e3
Restructure path handling a bit. Fixes #66.
Christian Kamm <kamm incasoftware de>
parents:
550
diff
changeset
|
162 if (!FileName::absolute(argobj)) |
7824c21a58e3
Restructure path handling a bit. Fixes #66.
Christian Kamm <kamm incasoftware de>
parents:
550
diff
changeset
|
163 { |
7824c21a58e3
Restructure path handling a bit. Fixes #66.
Christian Kamm <kamm incasoftware de>
parents:
550
diff
changeset
|
164 argobj = FileName::combine(path, argobj); |
7824c21a58e3
Restructure path handling a bit. Fixes #66.
Christian Kamm <kamm incasoftware de>
parents:
550
diff
changeset
|
165 } |
7824c21a58e3
Restructure path handling a bit. Fixes #66.
Christian Kamm <kamm incasoftware de>
parents:
550
diff
changeset
|
166 |
7824c21a58e3
Restructure path handling a bit. Fixes #66.
Christian Kamm <kamm incasoftware de>
parents:
550
diff
changeset
|
167 FileName::ensurePathExists(FileName::path(argobj)); |
7824c21a58e3
Restructure path handling a bit. Fixes #66.
Christian Kamm <kamm incasoftware de>
parents:
550
diff
changeset
|
168 |
708
fd5665da3a27
Hopefully sensible command switch handling. Changed default ext to .o on Windows.
Christian Kamm <kamm incasoftware de>
parents:
675
diff
changeset
|
169 // always append the extension! otherwise hard to make output switches consistent |
fd5665da3a27
Hopefully sensible command switch handling. Changed default ext to .o on Windows.
Christian Kamm <kamm incasoftware de>
parents:
675
diff
changeset
|
170 // if (forcename) |
fd5665da3a27
Hopefully sensible command switch handling. Changed default ext to .o on Windows.
Christian Kamm <kamm incasoftware de>
parents:
675
diff
changeset
|
171 // return new File(argobj); |
fd5665da3a27
Hopefully sensible command switch handling. Changed default ext to .o on Windows.
Christian Kamm <kamm incasoftware de>
parents:
675
diff
changeset
|
172 // else |
fd5665da3a27
Hopefully sensible command switch handling. Changed default ext to .o on Windows.
Christian Kamm <kamm incasoftware de>
parents:
675
diff
changeset
|
173 // allow for .o and .obj on windows |
fd5665da3a27
Hopefully sensible command switch handling. Changed default ext to .o on Windows.
Christian Kamm <kamm incasoftware de>
parents:
675
diff
changeset
|
174 #if _WIN32 |
fd5665da3a27
Hopefully sensible command switch handling. Changed default ext to .o on Windows.
Christian Kamm <kamm incasoftware de>
parents:
675
diff
changeset
|
175 if (ext == global.params.objdir && FileName::ext(argobj) |
fd5665da3a27
Hopefully sensible command switch handling. Changed default ext to .o on Windows.
Christian Kamm <kamm incasoftware de>
parents:
675
diff
changeset
|
176 && stricmp(FileName::ext(argobj), global.obj_ext_alt) == 0) |
580
7824c21a58e3
Restructure path handling a bit. Fixes #66.
Christian Kamm <kamm incasoftware de>
parents:
550
diff
changeset
|
177 return new File(argobj); |
708
fd5665da3a27
Hopefully sensible command switch handling. Changed default ext to .o on Windows.
Christian Kamm <kamm incasoftware de>
parents:
675
diff
changeset
|
178 #endif |
fd5665da3a27
Hopefully sensible command switch handling. Changed default ext to .o on Windows.
Christian Kamm <kamm incasoftware de>
parents:
675
diff
changeset
|
179 return new File(FileName::forceExt(argobj, ext)); |
336 | 180 } |
181 | |
580
7824c21a58e3
Restructure path handling a bit. Fixes #66.
Christian Kamm <kamm incasoftware de>
parents:
550
diff
changeset
|
182 void Module::buildTargetFiles() |
336 | 183 { |
604
a30fc28e8f23
Make creating and deleting of doc and hdr files dependent on whether doc and
Christian Kamm <kamm incasoftware de>
parents:
598
diff
changeset
|
184 if(objfile && |
a30fc28e8f23
Make creating and deleting of doc and hdr files dependent on whether doc and
Christian Kamm <kamm incasoftware de>
parents:
598
diff
changeset
|
185 (!doDocComment || docfile) && |
a30fc28e8f23
Make creating and deleting of doc and hdr files dependent on whether doc and
Christian Kamm <kamm incasoftware de>
parents:
598
diff
changeset
|
186 (!doHdrGen || hdrfile)) |
580
7824c21a58e3
Restructure path handling a bit. Fixes #66.
Christian Kamm <kamm incasoftware de>
parents:
550
diff
changeset
|
187 return; |
336 | 188 |
604
a30fc28e8f23
Make creating and deleting of doc and hdr files dependent on whether doc and
Christian Kamm <kamm incasoftware de>
parents:
598
diff
changeset
|
189 if(!objfile) |
675
bfe5229f9d8e
Disable bc output by default. Remove -dis. Add -output-bc, -output-ll, -output-s.
Christian Kamm <kamm incasoftware de>
parents:
664
diff
changeset
|
190 objfile = Module::buildFilePath(global.params.objname, global.params.objdir, global.obj_ext); |
604
a30fc28e8f23
Make creating and deleting of doc and hdr files dependent on whether doc and
Christian Kamm <kamm incasoftware de>
parents:
598
diff
changeset
|
191 if(doDocComment && !docfile) |
a30fc28e8f23
Make creating and deleting of doc and hdr files dependent on whether doc and
Christian Kamm <kamm incasoftware de>
parents:
598
diff
changeset
|
192 docfile = Module::buildFilePath(global.params.docname, global.params.docdir, global.doc_ext); |
a30fc28e8f23
Make creating and deleting of doc and hdr files dependent on whether doc and
Christian Kamm <kamm incasoftware de>
parents:
598
diff
changeset
|
193 if(doHdrGen && !hdrfile) |
a30fc28e8f23
Make creating and deleting of doc and hdr files dependent on whether doc and
Christian Kamm <kamm incasoftware de>
parents:
598
diff
changeset
|
194 hdrfile = Module::buildFilePath(global.params.hdrname, global.params.hdrdir, global.hdr_ext); |
598
13ff06605226
To prevert source-overwriting in the future, forbit output files with the same
Christian Kamm <kamm incasoftware de>
parents:
597
diff
changeset
|
195 |
13ff06605226
To prevert source-overwriting in the future, forbit output files with the same
Christian Kamm <kamm incasoftware de>
parents:
597
diff
changeset
|
196 // safety check: never allow obj, doc or hdr file to have the source file's name |
604
a30fc28e8f23
Make creating and deleting of doc and hdr files dependent on whether doc and
Christian Kamm <kamm incasoftware de>
parents:
598
diff
changeset
|
197 if(stricmp(FileName::name(objfile->name->str), FileName::name((char*)this->arg)) == 0) |
a30fc28e8f23
Make creating and deleting of doc and hdr files dependent on whether doc and
Christian Kamm <kamm incasoftware de>
parents:
598
diff
changeset
|
198 { |
a30fc28e8f23
Make creating and deleting of doc and hdr files dependent on whether doc and
Christian Kamm <kamm incasoftware de>
parents:
598
diff
changeset
|
199 error("Output object files with the same name as the source file are forbidden"); |
a30fc28e8f23
Make creating and deleting of doc and hdr files dependent on whether doc and
Christian Kamm <kamm incasoftware de>
parents:
598
diff
changeset
|
200 fatal(); |
a30fc28e8f23
Make creating and deleting of doc and hdr files dependent on whether doc and
Christian Kamm <kamm incasoftware de>
parents:
598
diff
changeset
|
201 } |
a30fc28e8f23
Make creating and deleting of doc and hdr files dependent on whether doc and
Christian Kamm <kamm incasoftware de>
parents:
598
diff
changeset
|
202 if(docfile && stricmp(FileName::name(docfile->name->str), FileName::name((char*)this->arg)) == 0) |
598
13ff06605226
To prevert source-overwriting in the future, forbit output files with the same
Christian Kamm <kamm incasoftware de>
parents:
597
diff
changeset
|
203 { |
604
a30fc28e8f23
Make creating and deleting of doc and hdr files dependent on whether doc and
Christian Kamm <kamm incasoftware de>
parents:
598
diff
changeset
|
204 error("Output doc files with the same name as the source file are forbidden"); |
a30fc28e8f23
Make creating and deleting of doc and hdr files dependent on whether doc and
Christian Kamm <kamm incasoftware de>
parents:
598
diff
changeset
|
205 fatal(); |
a30fc28e8f23
Make creating and deleting of doc and hdr files dependent on whether doc and
Christian Kamm <kamm incasoftware de>
parents:
598
diff
changeset
|
206 } |
a30fc28e8f23
Make creating and deleting of doc and hdr files dependent on whether doc and
Christian Kamm <kamm incasoftware de>
parents:
598
diff
changeset
|
207 if(hdrfile && stricmp(FileName::name(hdrfile->name->str), FileName::name((char*)this->arg)) == 0) |
a30fc28e8f23
Make creating and deleting of doc and hdr files dependent on whether doc and
Christian Kamm <kamm incasoftware de>
parents:
598
diff
changeset
|
208 { |
a30fc28e8f23
Make creating and deleting of doc and hdr files dependent on whether doc and
Christian Kamm <kamm incasoftware de>
parents:
598
diff
changeset
|
209 error("Output header files with the same name as the source file are forbidden"); |
598
13ff06605226
To prevert source-overwriting in the future, forbit output files with the same
Christian Kamm <kamm incasoftware de>
parents:
597
diff
changeset
|
210 fatal(); |
13ff06605226
To prevert source-overwriting in the future, forbit output files with the same
Christian Kamm <kamm incasoftware de>
parents:
597
diff
changeset
|
211 } |
336 | 212 } |
213 | |
214 void Module::deleteObjFile() | |
215 { | |
216 if (global.params.obj) | |
217 objfile->remove(); | |
218 //if (global.params.llvmBC) | |
580
7824c21a58e3
Restructure path handling a bit. Fixes #66.
Christian Kamm <kamm incasoftware de>
parents:
550
diff
changeset
|
219 //bcfile->remove(); |
604
a30fc28e8f23
Make creating and deleting of doc and hdr files dependent on whether doc and
Christian Kamm <kamm incasoftware de>
parents:
598
diff
changeset
|
220 if (doDocComment && docfile) |
336 | 221 docfile->remove(); |
222 } | |
223 | |
224 Module::~Module() | |
225 { | |
226 } | |
227 | |
228 const char *Module::kind() | |
229 { | |
230 return "module"; | |
231 } | |
232 | |
233 Module *Module::load(Loc loc, Array *packages, Identifier *ident) | |
234 { Module *m; | |
235 char *filename; | |
236 | |
237 //printf("Module::load(ident = '%s')\n", ident->toChars()); | |
238 | |
239 // Build module filename by turning: | |
240 // foo.bar.baz | |
241 // into: | |
242 // foo\bar\baz | |
243 filename = ident->toChars(); | |
244 if (packages && packages->dim) | |
245 { | |
246 OutBuffer buf; | |
247 int i; | |
248 | |
249 for (i = 0; i < packages->dim; i++) | |
250 { Identifier *pid = (Identifier *)packages->data[i]; | |
251 | |
252 buf.writestring(pid->toChars()); | |
253 #if _WIN32 | |
254 buf.writeByte('\\'); | |
255 #else | |
256 buf.writeByte('/'); | |
257 #endif | |
258 } | |
259 buf.writestring(filename); | |
260 buf.writeByte(0); | |
261 filename = (char *)buf.extractData(); | |
262 } | |
263 | |
264 m = new Module(filename, ident, 0, 0); | |
265 m->loc = loc; | |
266 | |
267 /* Search along global.path for .di file, then .d file. | |
268 */ | |
269 char *result = NULL; | |
270 FileName *fdi = FileName::forceExt(filename, global.hdr_ext); | |
271 FileName *fd = FileName::forceExt(filename, global.mars_ext); | |
272 char *sdi = fdi->toChars(); | |
273 char *sd = fd->toChars(); | |
274 | |
275 if (FileName::exists(sdi)) | |
276 result = sdi; | |
277 else if (FileName::exists(sd)) | |
278 result = sd; | |
279 else if (FileName::absolute(filename)) | |
280 ; | |
281 else if (!global.path) | |
282 ; | |
283 else | |
284 { | |
285 for (size_t i = 0; i < global.path->dim; i++) | |
286 { | |
287 char *p = (char *)global.path->data[i]; | |
288 char *n = FileName::combine(p, sdi); | |
289 if (FileName::exists(n)) | |
290 { result = n; | |
291 break; | |
292 } | |
293 mem.free(n); | |
294 n = FileName::combine(p, sd); | |
295 if (FileName::exists(n)) | |
296 { result = n; | |
297 break; | |
298 } | |
299 mem.free(n); | |
300 } | |
301 } | |
302 if (result) | |
303 m->srcfile = new File(result); | |
304 | |
305 if (global.params.verbose) | |
306 { | |
307 printf("import "); | |
308 if (packages) | |
309 { | |
310 for (size_t i = 0; i < packages->dim; i++) | |
311 { Identifier *pid = (Identifier *)packages->data[i]; | |
312 printf("%s.", pid->toChars()); | |
313 } | |
314 } | |
315 printf("%s\t(%s)\n", ident->toChars(), m->srcfile->toChars()); | |
316 } | |
317 | |
318 m->read(loc); | |
319 m->parse(); | |
320 | |
321 #ifdef IN_GCC | |
322 d_gcc_magic_module(m); | |
323 #endif | |
324 | |
325 return m; | |
326 } | |
327 | |
328 void Module::read(Loc loc) | |
329 { | |
330 //printf("Module::read('%s') file '%s'\n", toChars(), srcfile->toChars()); | |
331 if (srcfile->read()) | |
332 { error(loc, "cannot read file '%s'", srcfile->toChars()); | |
333 fatal(); | |
334 } | |
335 } | |
336 | |
337 inline unsigned readwordLE(unsigned short *p) | |
338 { | |
339 #if __I86__ | |
340 return *p; | |
341 #else | |
342 return (((unsigned char *)p)[1] << 8) | ((unsigned char *)p)[0]; | |
343 #endif | |
344 } | |
345 | |
346 inline unsigned readwordBE(unsigned short *p) | |
347 { | |
348 return (((unsigned char *)p)[0] << 8) | ((unsigned char *)p)[1]; | |
349 } | |
350 | |
351 inline unsigned readlongLE(unsigned *p) | |
352 { | |
353 #if __I86__ | |
354 return *p; | |
355 #else | |
356 return ((unsigned char *)p)[0] | | |
357 (((unsigned char *)p)[1] << 8) | | |
358 (((unsigned char *)p)[2] << 16) | | |
359 (((unsigned char *)p)[3] << 24); | |
360 #endif | |
361 } | |
362 | |
363 inline unsigned readlongBE(unsigned *p) | |
364 { | |
365 return ((unsigned char *)p)[3] | | |
366 (((unsigned char *)p)[2] << 8) | | |
367 (((unsigned char *)p)[1] << 16) | | |
368 (((unsigned char *)p)[0] << 24); | |
369 } | |
370 | |
371 #if IN_GCC | |
372 void Module::parse(bool dump_source) | |
373 #else | |
374 void Module::parse() | |
375 #endif | |
376 { char *srcname; | |
377 unsigned char *buf; | |
378 unsigned buflen; | |
379 unsigned le; | |
380 unsigned bom; | |
381 | |
382 //printf("Module::parse()\n"); | |
383 | |
384 srcname = srcfile->name->toChars(); | |
385 //printf("Module::parse(srcname = '%s')\n", srcname); | |
386 | |
387 buf = srcfile->buffer; | |
388 buflen = srcfile->len; | |
389 | |
390 if (buflen >= 2) | |
391 { | |
392 /* Convert all non-UTF-8 formats to UTF-8. | |
393 * BOM : http://www.unicode.org/faq/utf_bom.html | |
394 * 00 00 FE FF UTF-32BE, big-endian | |
395 * FF FE 00 00 UTF-32LE, little-endian | |
396 * FE FF UTF-16BE, big-endian | |
397 * FF FE UTF-16LE, little-endian | |
398 * EF BB BF UTF-8 | |
399 */ | |
400 | |
401 bom = 1; // assume there's a BOM | |
402 if (buf[0] == 0xFF && buf[1] == 0xFE) | |
403 { | |
404 if (buflen >= 4 && buf[2] == 0 && buf[3] == 0) | |
405 { // UTF-32LE | |
406 le = 1; | |
407 | |
408 Lutf32: | |
409 OutBuffer dbuf; | |
410 unsigned *pu = (unsigned *)(buf); | |
411 unsigned *pumax = &pu[buflen / 4]; | |
412 | |
413 if (buflen & 3) | |
414 { error("odd length of UTF-32 char source %u", buflen); | |
415 fatal(); | |
416 } | |
417 | |
418 dbuf.reserve(buflen / 4); | |
419 for (pu += bom; pu < pumax; pu++) | |
420 { unsigned u; | |
421 | |
422 u = le ? readlongLE(pu) : readlongBE(pu); | |
423 if (u & ~0x7F) | |
424 { | |
425 if (u > 0x10FFFF) | |
426 { error("UTF-32 value %08x greater than 0x10FFFF", u); | |
427 fatal(); | |
428 } | |
429 dbuf.writeUTF8(u); | |
430 } | |
431 else | |
432 dbuf.writeByte(u); | |
433 } | |
434 dbuf.writeByte(0); // add 0 as sentinel for scanner | |
435 buflen = dbuf.offset - 1; // don't include sentinel in count | |
436 buf = (unsigned char *) dbuf.extractData(); | |
437 } | |
438 else | |
439 { // UTF-16LE (X86) | |
440 // Convert it to UTF-8 | |
441 le = 1; | |
442 | |
443 Lutf16: | |
444 OutBuffer dbuf; | |
445 unsigned short *pu = (unsigned short *)(buf); | |
446 unsigned short *pumax = &pu[buflen / 2]; | |
447 | |
448 if (buflen & 1) | |
449 { error("odd length of UTF-16 char source %u", buflen); | |
450 fatal(); | |
451 } | |
452 | |
453 dbuf.reserve(buflen / 2); | |
454 for (pu += bom; pu < pumax; pu++) | |
455 { unsigned u; | |
456 | |
457 u = le ? readwordLE(pu) : readwordBE(pu); | |
458 if (u & ~0x7F) | |
459 { if (u >= 0xD800 && u <= 0xDBFF) | |
460 { unsigned u2; | |
461 | |
462 if (++pu > pumax) | |
463 { error("surrogate UTF-16 high value %04x at EOF", u); | |
464 fatal(); | |
465 } | |
466 u2 = le ? readwordLE(pu) : readwordBE(pu); | |
467 if (u2 < 0xDC00 || u2 > 0xDFFF) | |
468 { error("surrogate UTF-16 low value %04x out of range", u2); | |
469 fatal(); | |
470 } | |
471 u = (u - 0xD7C0) << 10; | |
472 u |= (u2 - 0xDC00); | |
473 } | |
474 else if (u >= 0xDC00 && u <= 0xDFFF) | |
475 { error("unpaired surrogate UTF-16 value %04x", u); | |
476 fatal(); | |
477 } | |
478 else if (u == 0xFFFE || u == 0xFFFF) | |
479 { error("illegal UTF-16 value %04x", u); | |
480 fatal(); | |
481 } | |
482 dbuf.writeUTF8(u); | |
483 } | |
484 else | |
485 dbuf.writeByte(u); | |
486 } | |
487 dbuf.writeByte(0); // add 0 as sentinel for scanner | |
488 buflen = dbuf.offset - 1; // don't include sentinel in count | |
489 buf = (unsigned char *) dbuf.extractData(); | |
490 } | |
491 } | |
492 else if (buf[0] == 0xFE && buf[1] == 0xFF) | |
493 { // UTF-16BE | |
494 le = 0; | |
495 goto Lutf16; | |
496 } | |
497 else if (buflen >= 4 && buf[0] == 0 && buf[1] == 0 && buf[2] == 0xFE && buf[3] == 0xFF) | |
498 { // UTF-32BE | |
499 le = 0; | |
500 goto Lutf32; | |
501 } | |
502 else if (buflen >= 3 && buf[0] == 0xEF && buf[1] == 0xBB && buf[2] == 0xBF) | |
503 { // UTF-8 | |
504 | |
505 buf += 3; | |
506 buflen -= 3; | |
507 } | |
508 else | |
509 { | |
510 /* There is no BOM. Make use of Arcane Jill's insight that | |
511 * the first char of D source must be ASCII to | |
512 * figure out the encoding. | |
513 */ | |
514 | |
515 bom = 0; | |
516 if (buflen >= 4) | |
517 { if (buf[1] == 0 && buf[2] == 0 && buf[3] == 0) | |
518 { // UTF-32LE | |
519 le = 1; | |
520 goto Lutf32; | |
521 } | |
522 else if (buf[0] == 0 && buf[1] == 0 && buf[2] == 0) | |
523 { // UTF-32BE | |
524 le = 0; | |
525 goto Lutf32; | |
526 } | |
527 } | |
528 if (buflen >= 2) | |
529 { | |
530 if (buf[1] == 0) | |
531 { // UTF-16LE | |
532 le = 1; | |
533 goto Lutf16; | |
534 } | |
535 else if (buf[0] == 0) | |
536 { // UTF-16BE | |
537 le = 0; | |
538 goto Lutf16; | |
539 } | |
540 } | |
541 | |
542 // It's UTF-8 | |
543 if (buf[0] >= 0x80) | |
544 { error("source file must start with BOM or ASCII character, not \\x%02X", buf[0]); | |
545 fatal(); | |
546 } | |
547 } | |
548 } | |
549 | |
550 #ifdef IN_GCC | |
551 // dump utf-8 encoded source | |
552 if (dump_source) | |
553 { // %% srcname could contain a path ... | |
554 d_gcc_dump_source(srcname, "utf-8", buf, buflen); | |
555 } | |
556 #endif | |
557 | |
558 /* If it starts with the string "Ddoc", then it's a documentation | |
559 * source file. | |
560 */ | |
561 if (buflen >= 4 && memcmp(buf, "Ddoc", 4) == 0) | |
562 { | |
563 comment = buf + 4; | |
564 isDocFile = 1; | |
565 return; | |
566 } | |
567 if (isHtml) | |
568 { | |
569 OutBuffer *dbuf = new OutBuffer(); | |
570 Html h(srcname, buf, buflen); | |
571 h.extractCode(dbuf); | |
572 buf = dbuf->data; | |
573 buflen = dbuf->offset; | |
574 #ifdef IN_GCC | |
575 // dump extracted source | |
576 if (dump_source) | |
577 d_gcc_dump_source(srcname, "d.utf-8", buf, buflen); | |
578 #endif | |
579 } | |
580 Parser p(this, buf, buflen, docfile != NULL); | |
581 p.nextToken(); | |
582 members = p.parseModule(); | |
583 md = p.md; | |
584 numlines = p.loc.linnum; | |
585 | |
586 DsymbolTable *dst; | |
587 | |
588 if (md) | |
589 { this->ident = md->id; | |
590 dst = Package::resolve(md->packages, &this->parent, NULL); | |
591 } | |
592 else | |
593 { | |
594 dst = modules; | |
595 | |
596 /* Check to see if module name is a valid identifier | |
597 */ | |
598 if (!Lexer::isValidIdentifier(this->ident->toChars())) | |
599 error("has non-identifier characters in filename, use module declaration instead"); | |
600 } | |
601 | |
602 // Update global list of modules | |
603 if (!dst->insert(this)) | |
604 { | |
605 if (md) | |
606 error(loc, "is in multiple packages %s", md->toChars()); | |
607 else | |
608 error(loc, "is in multiple defined"); | |
609 } | |
610 else | |
611 { | |
612 amodules.push(this); | |
613 } | |
614 } | |
615 | |
751
dc8b8b7ea0c1
Fix compile-time warnings. Adjust include in d-asm-i386.
Christian Kamm <kamm incasoftware de>
parents:
708
diff
changeset
|
616 void Module::semantic(Scope* unused_sc) |
336 | 617 { int i; |
618 | |
619 if (semanticstarted) | |
620 return; | |
621 | |
622 //printf("+Module::semantic(this = %p, '%s'): parent = %p\n", this, toChars(), parent); | |
623 semanticstarted = 1; | |
624 | |
625 // Note that modules get their own scope, from scratch. | |
626 // This is so regardless of where in the syntax a module | |
627 // gets imported, it is unaffected by context. | |
628 Scope *sc = Scope::createGlobal(this); // create root scope | |
629 | |
630 //printf("Module = %p, linkage = %d\n", sc->scopesym, sc->linkage); | |
631 | |
632 // Add import of "object" if this module isn't "object" | |
633 if (ident != Id::object) | |
634 { | |
635 Import *im = new Import(0, NULL, Id::object, NULL, 0); | |
636 members->shift(im); | |
637 } | |
638 | |
639 // Add all symbols into module's symbol table | |
640 symtab = new DsymbolTable(); | |
641 for (i = 0; i < members->dim; i++) | |
642 { Dsymbol *s; | |
643 | |
644 s = (Dsymbol *)members->data[i]; | |
645 s->addMember(NULL, sc->scopesym, 1); | |
646 } | |
647 | |
648 // Pass 1 semantic routines: do public side of the definition | |
649 for (i = 0; i < members->dim; i++) | |
650 { Dsymbol *s; | |
651 | |
652 s = (Dsymbol *)members->data[i]; | |
653 //printf("\tModule('%s'): '%s'.semantic()\n", toChars(), s->toChars()); | |
654 s->semantic(sc); | |
655 runDeferredSemantic(); | |
656 } | |
657 | |
658 sc = sc->pop(); | |
659 sc->pop(); | |
660 semanticdone = semanticstarted; | |
661 //printf("-Module::semantic(this = %p, '%s'): parent = %p\n", this, toChars(), parent); | |
662 } | |
663 | |
751
dc8b8b7ea0c1
Fix compile-time warnings. Adjust include in d-asm-i386.
Christian Kamm <kamm incasoftware de>
parents:
708
diff
changeset
|
664 void Module::semantic2(Scope* unused_sc) |
336 | 665 { int i; |
666 | |
667 if (deferred.dim) | |
668 { | |
669 for (int i = 0; i < deferred.dim; i++) | |
670 { | |
671 Dsymbol *sd = (Dsymbol *)deferred.data[i]; | |
672 | |
673 sd->error("unable to resolve forward reference in definition"); | |
674 } | |
675 return; | |
676 } | |
677 //printf("Module::semantic2('%s'): parent = %p\n", toChars(), parent); | |
678 if (semanticstarted >= 2) | |
679 return; | |
680 assert(semanticstarted == 1); | |
681 semanticstarted = 2; | |
682 | |
683 // Note that modules get their own scope, from scratch. | |
684 // This is so regardless of where in the syntax a module | |
685 // gets imported, it is unaffected by context. | |
686 Scope *sc = Scope::createGlobal(this); // create root scope | |
687 //printf("Module = %p\n", sc.scopesym); | |
688 | |
689 // Pass 2 semantic routines: do initializers and function bodies | |
690 for (i = 0; i < members->dim; i++) | |
691 { Dsymbol *s; | |
692 | |
693 s = (Dsymbol *)members->data[i]; | |
694 s->semantic2(sc); | |
695 } | |
696 | |
697 sc = sc->pop(); | |
698 sc->pop(); | |
699 semanticdone = semanticstarted; | |
700 //printf("-Module::semantic2('%s'): parent = %p\n", toChars(), parent); | |
701 } | |
702 | |
751
dc8b8b7ea0c1
Fix compile-time warnings. Adjust include in d-asm-i386.
Christian Kamm <kamm incasoftware de>
parents:
708
diff
changeset
|
703 void Module::semantic3(Scope* unused_sc) |
336 | 704 { int i; |
705 | |
706 //printf("Module::semantic3('%s'): parent = %p\n", toChars(), parent); | |
707 if (semanticstarted >= 3) | |
708 return; | |
709 assert(semanticstarted == 2); | |
710 semanticstarted = 3; | |
711 | |
712 // Note that modules get their own scope, from scratch. | |
713 // This is so regardless of where in the syntax a module | |
714 // gets imported, it is unaffected by context. | |
715 Scope *sc = Scope::createGlobal(this); // create root scope | |
716 //printf("Module = %p\n", sc.scopesym); | |
717 | |
718 // Pass 3 semantic routines: do initializers and function bodies | |
719 for (i = 0; i < members->dim; i++) | |
720 { Dsymbol *s; | |
721 | |
722 s = (Dsymbol *)members->data[i]; | |
723 //printf("Module %s: %s.semantic3()\n", toChars(), s->toChars()); | |
724 s->semantic3(sc); | |
725 } | |
726 | |
727 sc = sc->pop(); | |
728 sc->pop(); | |
729 semanticdone = semanticstarted; | |
730 } | |
731 | |
732 void Module::inlineScan() | |
733 { int i; | |
734 | |
735 if (semanticstarted >= 4) | |
736 return; | |
737 assert(semanticstarted == 3); | |
738 semanticstarted = 4; | |
739 | |
740 // Note that modules get their own scope, from scratch. | |
741 // This is so regardless of where in the syntax a module | |
742 // gets imported, it is unaffected by context. | |
743 //printf("Module = %p\n", sc.scopesym); | |
744 | |
745 for (i = 0; i < members->dim; i++) | |
746 { Dsymbol *s; | |
747 | |
748 s = (Dsymbol *)members->data[i]; | |
749 //if (global.params.verbose) | |
750 //printf("inline scan symbol %s\n", s->toChars()); | |
751 | |
752 s->inlineScan(); | |
753 } | |
754 semanticdone = semanticstarted; | |
755 } | |
756 | |
757 /**************************************************** | |
758 */ | |
759 | |
580
7824c21a58e3
Restructure path handling a bit. Fixes #66.
Christian Kamm <kamm incasoftware de>
parents:
550
diff
changeset
|
760 // is this used anywhere? |
7824c21a58e3
Restructure path handling a bit. Fixes #66.
Christian Kamm <kamm incasoftware de>
parents:
550
diff
changeset
|
761 /* |
336 | 762 void Module::gensymfile() |
763 { | |
764 OutBuffer buf; | |
765 HdrGenState hgs; | |
766 | |
767 //printf("Module::gensymfile()\n"); | |
768 | |
769 buf.printf("// Sym file generated from '%s'", srcfile->toChars()); | |
770 buf.writenl(); | |
771 | |
772 for (int i = 0; i < members->dim; i++) | |
773 { Dsymbol *s = (Dsymbol *)members->data[i]; | |
774 | |
775 s->toCBuffer(&buf, &hgs); | |
776 } | |
777 | |
778 // Transfer image to file | |
779 symfile->setbuffer(buf.data, buf.offset); | |
780 buf.data = NULL; | |
781 | |
782 symfile->writev(); | |
580
7824c21a58e3
Restructure path handling a bit. Fixes #66.
Christian Kamm <kamm incasoftware de>
parents:
550
diff
changeset
|
783 }*/ |
336 | 784 |
785 /********************************** | |
786 * Determine if we need to generate an instance of ModuleInfo | |
787 * for this Module. | |
788 */ | |
789 | |
790 int Module::needModuleInfo() | |
791 { | |
550
cbe08531430f
Removed unimplemented switches.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
510
diff
changeset
|
792 return needmoduleinfo; |
336 | 793 } |
794 | |
795 Dsymbol *Module::search(Loc loc, Identifier *ident, int flags) | |
796 { | |
797 /* Since modules can be circularly referenced, | |
798 * need to stop infinite recursive searches. | |
799 */ | |
800 | |
801 //printf("%s Module::search('%s', flags = %d) insearch = %d\n", toChars(), ident->toChars(), flags, insearch); | |
802 Dsymbol *s; | |
803 if (insearch) | |
804 s = NULL; | |
805 else if (searchCacheIdent == ident && searchCacheFlags == flags) | |
806 s = searchCacheSymbol; | |
807 else | |
808 { | |
809 insearch = 1; | |
810 s = ScopeDsymbol::search(loc, ident, flags); | |
811 insearch = 0; | |
812 | |
813 searchCacheIdent = ident; | |
814 searchCacheSymbol = s; | |
815 searchCacheFlags = flags; | |
816 } | |
817 return s; | |
818 } | |
819 | |
820 /******************************************* | |
821 * Can't run semantic on s now, try again later. | |
822 */ | |
823 | |
824 void Module::addDeferredSemantic(Dsymbol *s) | |
825 { | |
826 // Don't add it if it is already there | |
827 for (int i = 0; i < deferred.dim; i++) | |
828 { | |
829 Dsymbol *sd = (Dsymbol *)deferred.data[i]; | |
830 | |
831 if (sd == s) | |
832 return; | |
833 } | |
834 | |
835 //printf("Module::addDeferredSemantic('%s')\n", s->toChars()); | |
836 deferred.push(s); | |
837 } | |
838 | |
839 | |
840 /****************************************** | |
841 * Run semantic() on deferred symbols. | |
842 */ | |
843 | |
844 void Module::runDeferredSemantic() | |
845 { | |
846 size_t len; | |
847 | |
848 static int nested; | |
849 if (nested) | |
850 return; | |
851 //if (deferred.dim) printf("+Module::runDeferredSemantic('%s'), len = %d\n", toChars(), deferred.dim); | |
852 nested++; | |
853 | |
854 do | |
855 { | |
856 dprogress = 0; | |
857 len = deferred.dim; | |
858 if (!len) | |
859 break; | |
860 | |
861 Dsymbol **todo; | |
862 Dsymbol *tmp; | |
863 if (len == 1) | |
864 { | |
865 todo = &tmp; | |
866 } | |
867 else | |
868 { | |
869 todo = (Dsymbol **)alloca(len * sizeof(Dsymbol *)); | |
870 assert(todo); | |
871 } | |
872 memcpy(todo, deferred.data, len * sizeof(Dsymbol *)); | |
873 deferred.setDim(0); | |
874 | |
875 for (int i = 0; i < len; i++) | |
876 { | |
877 Dsymbol *s = todo[i]; | |
878 | |
879 s->semantic(NULL); | |
880 //printf("deferred: %s, parent = %s\n", s->toChars(), s->parent->toChars()); | |
881 } | |
882 //printf("\tdeferred.dim = %d, len = %d, dprogress = %d\n", deferred.dim, len, dprogress); | |
883 } while (deferred.dim < len || dprogress); // while making progress | |
884 nested--; | |
885 //printf("-Module::runDeferredSemantic('%s'), len = %d\n", toChars(), deferred.dim); | |
886 } | |
887 | |
888 /* =========================== ModuleDeclaration ===================== */ | |
889 | |
890 ModuleDeclaration::ModuleDeclaration(Array *packages, Identifier *id) | |
891 { | |
892 this->packages = packages; | |
893 this->id = id; | |
894 } | |
895 | |
896 char *ModuleDeclaration::toChars() | |
897 { | |
898 OutBuffer buf; | |
899 int i; | |
900 | |
901 if (packages && packages->dim) | |
902 { | |
903 for (i = 0; i < packages->dim; i++) | |
904 { Identifier *pid = (Identifier *)packages->data[i]; | |
905 | |
906 buf.writestring(pid->toChars()); | |
907 buf.writeByte('.'); | |
908 } | |
909 } | |
910 buf.writestring(id->toChars()); | |
911 buf.writeByte(0); | |
912 return (char *)buf.extractData(); | |
913 } | |
914 | |
915 /* =========================== Package ===================== */ | |
916 | |
917 Package::Package(Identifier *ident) | |
918 : ScopeDsymbol(ident) | |
919 { | |
920 } | |
921 | |
922 | |
923 const char *Package::kind() | |
924 { | |
925 return "package"; | |
926 } | |
927 | |
928 | |
929 DsymbolTable *Package::resolve(Array *packages, Dsymbol **pparent, Package **ppkg) | |
930 { | |
931 DsymbolTable *dst = Module::modules; | |
932 Dsymbol *parent = NULL; | |
933 | |
934 //printf("Package::resolve()\n"); | |
935 if (ppkg) | |
936 *ppkg = NULL; | |
937 | |
938 if (packages) | |
939 { int i; | |
940 | |
941 for (i = 0; i < packages->dim; i++) | |
942 { Identifier *pid = (Identifier *)packages->data[i]; | |
943 Dsymbol *p; | |
944 | |
945 p = dst->lookup(pid); | |
946 if (!p) | |
947 { | |
948 p = new Package(pid); | |
949 dst->insert(p); | |
950 p->parent = parent; | |
951 ((ScopeDsymbol *)p)->symtab = new DsymbolTable(); | |
952 } | |
953 else | |
954 { | |
955 assert(p->isPackage()); | |
956 if (p->isModule()) | |
957 { p->error("module and package have the same name"); | |
958 fatal(); | |
959 break; | |
960 } | |
961 } | |
962 parent = p; | |
963 dst = ((Package *)p)->symtab; | |
964 if (ppkg && !*ppkg) | |
965 *ppkg = (Package *)p; | |
966 } | |
967 if (pparent) | |
968 { | |
969 *pparent = parent; | |
970 } | |
971 } | |
972 return dst; | |
973 } |