Mercurial > projects > ldc
annotate dmd/doc.c @ 1650:40bd4a0d4870
Update to work with LLVM 2.7.
Removed use of dyn_cast, llvm no compiles
without exceptions and rtti by
default. We do need exceptions for the libconfig stuff, but rtti isn't
necessary (anymore).
Debug info needs to be rewritten, as in LLVM 2.7 the format has
completely changed. To have something to look at while rewriting, the
old code has been wrapped inside #ifndef DISABLE_DEBUG_INFO , this means
that you have to define this to compile at the moment.
Updated tango 0.99.9 patch to include updated EH runtime code, which is
needed for LLVM 2.7 as well.
author | Tomas Lindquist Olsen |
---|---|
date | Wed, 19 May 2010 12:42:32 +0200 |
parents | c61782a76dff |
children |
rev | line source |
---|---|
159 | 1 |
2 // Compiler implementation of the D programming language | |
1587 | 3 // Copyright (c) 1999-2009 by Digital Mars |
159 | 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 // This implements the Ddoc capability. | |
12 | |
13 #include <stdio.h> | |
14 #include <string.h> | |
15 #include <time.h> | |
16 #include <ctype.h> | |
17 #include <assert.h> | |
18 | |
1103
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
876
diff
changeset
|
19 #include "rmem.h" |
159 | 20 #include "root.h" |
21 | |
22 #include "mars.h" | |
23 #include "dsymbol.h" | |
24 #include "macro.h" | |
25 #include "template.h" | |
26 #include "lexer.h" | |
27 #include "aggregate.h" | |
28 #include "declaration.h" | |
29 #include "enum.h" | |
30 #include "id.h" | |
31 #include "module.h" | |
32 #include "scope.h" | |
33 #include "hdrgen.h" | |
34 #include "doc.h" | |
35 #include "mtype.h" | |
1587 | 36 #include "utf.h" |
159 | 37 |
38 struct Escape | |
39 { | |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
571
diff
changeset
|
40 const char *strings[256]; |
159 | 41 |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
571
diff
changeset
|
42 static const char *escapeChar(unsigned c); |
159 | 43 }; |
44 | |
45 struct Section | |
46 { | |
47 unsigned char *name; | |
48 unsigned namelen; | |
49 | |
50 unsigned char *body; | |
51 unsigned bodylen; | |
52 | |
53 int nooutput; | |
54 | |
55 virtual void write(DocComment *dc, Scope *sc, Dsymbol *s, OutBuffer *buf); | |
56 }; | |
57 | |
58 struct ParamSection : Section | |
59 { | |
60 void write(DocComment *dc, Scope *sc, Dsymbol *s, OutBuffer *buf); | |
61 }; | |
62 | |
63 struct MacroSection : Section | |
64 { | |
65 void write(DocComment *dc, Scope *sc, Dsymbol *s, OutBuffer *buf); | |
66 }; | |
67 | |
68 struct DocComment | |
69 { | |
70 Array sections; // Section*[] | |
71 | |
72 Section *summary; | |
73 Section *copyright; | |
74 Section *macros; | |
75 Macro **pmacrotable; | |
76 Escape **pescapetable; | |
77 | |
78 DocComment(); | |
79 | |
80 static DocComment *parse(Scope *sc, Dsymbol *s, unsigned char *comment); | |
81 static void parseMacros(Escape **pescapetable, Macro **pmacrotable, unsigned char *m, unsigned mlen); | |
82 static void parseEscapes(Escape **pescapetable, unsigned char *textstart, unsigned textlen); | |
83 | |
84 void parseSections(unsigned char *comment); | |
85 void writeSections(Scope *sc, Dsymbol *s, OutBuffer *buf); | |
86 }; | |
87 | |
88 | |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
571
diff
changeset
|
89 int cmp(const char *stringz, void *s, size_t slen); |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
571
diff
changeset
|
90 int icmp(const char *stringz, void *s, size_t slen); |
159 | 91 int isDitto(unsigned char *comment); |
92 unsigned char *skipwhitespace(unsigned char *p); | |
1587 | 93 unsigned skiptoident(OutBuffer *buf, size_t i); |
94 unsigned skippastident(OutBuffer *buf, size_t i); | |
95 unsigned skippastURL(OutBuffer *buf, size_t i); | |
159 | 96 void highlightText(Scope *sc, Dsymbol *s, OutBuffer *buf, unsigned offset); |
97 void highlightCode(Scope *sc, Dsymbol *s, OutBuffer *buf, unsigned offset); | |
98 void highlightCode2(Scope *sc, Dsymbol *s, OutBuffer *buf, unsigned offset); | |
1607
207a8a438dea
Merge DMD r253: refactor: Argument => Parameter
Leandro Lucarella <llucax@gmail.com>
parents:
1587
diff
changeset
|
99 Parameter *isFunctionParameter(Dsymbol *s, unsigned char *p, unsigned len); |
159 | 100 |
1587 | 101 int isIdStart(unsigned char *p); |
102 int isIdTail(unsigned char *p); | |
103 int utfStride(unsigned char *p); | |
104 | |
159 | 105 static unsigned char ddoc_default[] = "\ |
106 DDOC = <html><head>\n\ | |
107 <META http-equiv=\"content-type\" content=\"text/html; charset=utf-8\">\n\ | |
108 <title>$(TITLE)</title>\n\ | |
109 </head><body>\n\ | |
110 <h1>$(TITLE)</h1>\n\ | |
111 $(BODY)\n\ | |
112 <hr>$(SMALL Page generated by $(LINK2 http://www.digitalmars.com/d/1.0/ddoc.html, Ddoc). $(COPYRIGHT))\n\ | |
113 </body></html>\n\ | |
114 \n\ | |
115 B = <b>$0</b>\n\ | |
116 I = <i>$0</i>\n\ | |
117 U = <u>$0</u>\n\ | |
118 P = <p>$0</p>\n\ | |
119 DL = <dl>$0</dl>\n\ | |
120 DT = <dt>$0</dt>\n\ | |
121 DD = <dd>$0</dd>\n\ | |
122 TABLE = <table>$0</table>\n\ | |
123 TR = <tr>$0</tr>\n\ | |
124 TH = <th>$0</th>\n\ | |
125 TD = <td>$0</td>\n\ | |
126 OL = <ol>$0</ol>\n\ | |
127 UL = <ul>$0</ul>\n\ | |
128 LI = <li>$0</li>\n\ | |
129 BIG = <big>$0</big>\n\ | |
130 SMALL = <small>$0</small>\n\ | |
131 BR = <br>\n\ | |
132 LINK = <a href=\"$0\">$0</a>\n\ | |
133 LINK2 = <a href=\"$1\">$+</a>\n\ | |
134 \n\ | |
135 RED = <font color=red>$0</font>\n\ | |
136 BLUE = <font color=blue>$0</font>\n\ | |
137 GREEN = <font color=green>$0</font>\n\ | |
138 YELLOW =<font color=yellow>$0</font>\n\ | |
139 BLACK = <font color=black>$0</font>\n\ | |
140 WHITE = <font color=white>$0</font>\n\ | |
141 \n\ | |
142 D_CODE = <pre class=\"d_code\">$0</pre>\n\ | |
143 D_COMMENT = $(GREEN $0)\n\ | |
144 D_STRING = $(RED $0)\n\ | |
145 D_KEYWORD = $(BLUE $0)\n\ | |
146 D_PSYMBOL = $(U $0)\n\ | |
147 D_PARAM = $(I $0)\n\ | |
148 \n\ | |
149 DDOC_COMMENT = <!-- $0 -->\n\ | |
150 DDOC_DECL = $(DT $(BIG $0))\n\ | |
151 DDOC_DECL_DD = $(DD $0)\n\ | |
152 DDOC_DITTO = $(BR)$0\n\ | |
153 DDOC_SECTIONS = $0\n\ | |
154 DDOC_SUMMARY = $0$(BR)$(BR)\n\ | |
155 DDOC_DESCRIPTION = $0$(BR)$(BR)\n\ | |
156 DDOC_AUTHORS = $(B Authors:)$(BR)\n$0$(BR)$(BR)\n\ | |
157 DDOC_BUGS = $(RED BUGS:)$(BR)\n$0$(BR)$(BR)\n\ | |
158 DDOC_COPYRIGHT = $(B Copyright:)$(BR)\n$0$(BR)$(BR)\n\ | |
159 DDOC_DATE = $(B Date:)$(BR)\n$0$(BR)$(BR)\n\ | |
160 DDOC_DEPRECATED = $(RED Deprecated:)$(BR)\n$0$(BR)$(BR)\n\ | |
161 DDOC_EXAMPLES = $(B Examples:)$(BR)\n$0$(BR)$(BR)\n\ | |
162 DDOC_HISTORY = $(B History:)$(BR)\n$0$(BR)$(BR)\n\ | |
163 DDOC_LICENSE = $(B License:)$(BR)\n$0$(BR)$(BR)\n\ | |
164 DDOC_RETURNS = $(B Returns:)$(BR)\n$0$(BR)$(BR)\n\ | |
165 DDOC_SEE_ALSO = $(B See Also:)$(BR)\n$0$(BR)$(BR)\n\ | |
166 DDOC_STANDARDS = $(B Standards:)$(BR)\n$0$(BR)$(BR)\n\ | |
167 DDOC_THROWS = $(B Throws:)$(BR)\n$0$(BR)$(BR)\n\ | |
168 DDOC_VERSION = $(B Version:)$(BR)\n$0$(BR)$(BR)\n\ | |
169 DDOC_SECTION_H = $(B $0)$(BR)\n\ | |
170 DDOC_SECTION = $0$(BR)$(BR)\n\ | |
171 DDOC_MEMBERS = $(DL $0)\n\ | |
172 DDOC_MODULE_MEMBERS = $(DDOC_MEMBERS $0)\n\ | |
173 DDOC_CLASS_MEMBERS = $(DDOC_MEMBERS $0)\n\ | |
174 DDOC_STRUCT_MEMBERS = $(DDOC_MEMBERS $0)\n\ | |
175 DDOC_ENUM_MEMBERS = $(DDOC_MEMBERS $0)\n\ | |
176 DDOC_TEMPLATE_MEMBERS = $(DDOC_MEMBERS $0)\n\ | |
177 DDOC_PARAMS = $(B Params:)$(BR)\n$(TABLE $0)$(BR)\n\ | |
178 DDOC_PARAM_ROW = $(TR $0)\n\ | |
179 DDOC_PARAM_ID = $(TD $0)\n\ | |
180 DDOC_PARAM_DESC = $(TD $0)\n\ | |
181 DDOC_BLANKLINE = $(BR)$(BR)\n\ | |
182 \n\ | |
183 DDOC_PSYMBOL = $(U $0)\n\ | |
184 DDOC_KEYWORD = $(B $0)\n\ | |
185 DDOC_PARAM = $(I $0)\n\ | |
186 \n\ | |
187 ESCAPES = /</</\n\ | |
188 />/>/\n\ | |
189 /&/&/\n\ | |
190 "; | |
191 | |
192 static char ddoc_decl_s[] = "$(DDOC_DECL "; | |
193 static char ddoc_decl_e[] = ")\n"; | |
194 | |
195 static char ddoc_decl_dd_s[] = "$(DDOC_DECL_DD "; | |
196 static char ddoc_decl_dd_e[] = ")\n"; | |
197 | |
198 | |
199 /**************************************************** | |
200 */ | |
201 | |
202 void Module::gendocfile() | |
203 { | |
204 static OutBuffer mbuf; | |
205 static int mbuf_done; | |
206 | |
207 OutBuffer buf; | |
208 | |
209 //printf("Module::gendocfile()\n"); | |
210 | |
211 if (!mbuf_done) // if not already read the ddoc files | |
212 { mbuf_done = 1; | |
213 | |
214 // Use our internal default | |
215 mbuf.write(ddoc_default, sizeof(ddoc_default) - 1); | |
216 | |
217 // Override with DDOCFILE specified in the sc.ini file | |
218 char *p = getenv("DDOCFILE"); | |
219 if (p) | |
220 global.params.ddocfiles->shift(p); | |
221 | |
222 // Override with the ddoc macro files from the command line | |
223 for (int i = 0; i < global.params.ddocfiles->dim; i++) | |
224 { | |
225 FileName f((char *)global.params.ddocfiles->data[i], 0); | |
226 File file(&f); | |
227 file.readv(); | |
228 // BUG: convert file contents to UTF-8 before use | |
229 | |
230 //printf("file: '%.*s'\n", file.len, file.buffer); | |
231 mbuf.write(file.buffer, file.len); | |
232 } | |
233 } | |
234 DocComment::parseMacros(&escapetable, ¯otable, mbuf.data, mbuf.offset); | |
235 | |
236 Scope *sc = Scope::createGlobal(this); // create root scope | |
237 sc->docbuf = &buf; | |
238 | |
239 DocComment *dc = DocComment::parse(sc, this, comment); | |
240 dc->pmacrotable = ¯otable; | |
241 dc->pescapetable = &escapetable; | |
242 | |
243 // Generate predefined macros | |
244 | |
245 // Set the title to be the name of the module | |
1587 | 246 { const char *p = toPrettyChars(); |
159 | 247 Macro::define(¯otable, (unsigned char *)"TITLE", 5, (unsigned char *)p, strlen(p)); |
248 } | |
249 | |
250 time_t t; | |
251 time(&t); | |
252 char *p = ctime(&t); | |
253 p = mem.strdup(p); | |
254 Macro::define(¯otable, (unsigned char *)"DATETIME", 8, (unsigned char *)p, strlen(p)); | |
255 Macro::define(¯otable, (unsigned char *)"YEAR", 4, (unsigned char *)p + 20, 4); | |
256 | |
257 char *docfilename = docfile->toChars(); | |
258 Macro::define(¯otable, (unsigned char *)"DOCFILENAME", 11, (unsigned char *)docfilename, strlen(docfilename)); | |
259 | |
260 if (dc->copyright) | |
261 { | |
262 dc->copyright->nooutput = 1; | |
263 Macro::define(¯otable, (unsigned char *)"COPYRIGHT", 9, dc->copyright->body, dc->copyright->bodylen); | |
264 } | |
265 | |
266 buf.printf("$(DDOC_COMMENT Generated by Ddoc from %s)\n", srcfile->toChars()); | |
267 if (isDocFile) | |
268 { | |
269 size_t commentlen = strlen((char *)comment); | |
270 if (dc->macros) | |
271 { | |
272 commentlen = dc->macros->name - comment; | |
273 dc->macros->write(dc, sc, this, sc->docbuf); | |
274 } | |
275 sc->docbuf->write(comment, commentlen); | |
276 highlightText(NULL, this, sc->docbuf, 0); | |
277 } | |
278 else | |
279 { | |
280 dc->writeSections(sc, this, sc->docbuf); | |
281 emitMemberComments(sc); | |
282 } | |
283 | |
284 //printf("BODY= '%.*s'\n", buf.offset, buf.data); | |
285 Macro::define(¯otable, (unsigned char *)"BODY", 4, buf.data, buf.offset); | |
286 | |
287 OutBuffer buf2; | |
288 buf2.writestring("$(DDOC)\n"); | |
289 unsigned end = buf2.offset; | |
290 macrotable->expand(&buf2, 0, &end, NULL, 0); | |
291 | |
292 #if 1 | |
293 /* Remove all the escape sequences from buf2, | |
294 * and make CR-LF the newline. | |
295 */ | |
296 { | |
297 buf.setsize(0); | |
298 buf.reserve(buf2.offset); | |
299 unsigned char *p = buf2.data; | |
300 for (unsigned j = 0; j < buf2.offset; j++) | |
301 { | |
302 unsigned char c = p[j]; | |
303 if (c == 0xFF && j + 1 < buf2.offset) | |
304 { | |
305 j++; | |
306 continue; | |
307 } | |
308 if (c == '\n') | |
309 buf.writeByte('\r'); | |
310 else if (c == '\r') | |
311 { | |
312 buf.writestring("\r\n"); | |
313 if (j + 1 < buf2.offset && p[j + 1] == '\n') | |
314 { | |
315 j++; | |
316 } | |
317 continue; | |
318 } | |
319 buf.writeByte(c); | |
320 } | |
321 } | |
322 | |
323 // Transfer image to file | |
324 assert(docfile); | |
325 docfile->setbuffer(buf.data, buf.offset); | |
326 docfile->ref = 1; | |
327 char *pt = FileName::path(docfile->toChars()); | |
328 if (*pt) | |
329 FileName::ensurePathExists(pt); | |
330 mem.free(pt); | |
331 docfile->writev(); | |
332 #else | |
333 /* Remove all the escape sequences from buf2 | |
334 */ | |
335 { unsigned i = 0; | |
336 unsigned char *p = buf2.data; | |
337 for (unsigned j = 0; j < buf2.offset; j++) | |
338 { | |
339 if (p[j] == 0xFF && j + 1 < buf2.offset) | |
340 { | |
341 j++; | |
342 continue; | |
343 } | |
344 p[i] = p[j]; | |
345 i++; | |
346 } | |
347 buf2.setsize(i); | |
348 } | |
349 | |
350 // Transfer image to file | |
351 docfile->setbuffer(buf2.data, buf2.offset); | |
352 docfile->ref = 1; | |
353 char *pt = FileName::path(docfile->toChars()); | |
354 if (*pt) | |
355 FileName::ensurePathExists(pt); | |
356 mem.free(pt); | |
357 docfile->writev(); | |
358 #endif | |
359 } | |
360 | |
361 /******************************* emitComment **********************************/ | |
362 | |
363 /* | |
364 * Emit doc comment to documentation file | |
365 */ | |
366 | |
367 void Dsymbol::emitDitto(Scope *sc) | |
368 { | |
369 //printf("Dsymbol::emitDitto() %s %s\n", kind(), toChars()); | |
370 OutBuffer *buf = sc->docbuf; | |
371 unsigned o; | |
372 OutBuffer b; | |
373 | |
374 b.writestring("$(DDOC_DITTO "); | |
375 o = b.offset; | |
376 toDocBuffer(&b); | |
377 //printf("b: '%.*s'\n", b.offset, b.data); | |
378 /* If 'this' is a function template, then highlightCode() was | |
379 * already run by FuncDeclaration::toDocbuffer(). | |
380 */ | |
381 TemplateDeclaration *td; | |
382 if (parent && | |
383 (td = parent->isTemplateDeclaration()) != NULL && | |
384 td->onemember == this) | |
385 { | |
386 } | |
387 else | |
388 highlightCode(sc, this, &b, o); | |
389 b.writeByte(')'); | |
390 buf->spread(sc->lastoffset, b.offset); | |
391 memcpy(buf->data + sc->lastoffset, b.data, b.offset); | |
392 sc->lastoffset += b.offset; | |
393 } | |
394 | |
395 void ScopeDsymbol::emitMemberComments(Scope *sc) | |
396 { | |
336 | 397 //printf("ScopeDsymbol::emitMemberComments() %s\n", toChars()); |
159 | 398 OutBuffer *buf = sc->docbuf; |
399 | |
400 if (members) | |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
571
diff
changeset
|
401 { const char *m = "$(DDOC_MEMBERS \n"; |
159 | 402 |
403 if (isModule()) | |
404 m = "$(DDOC_MODULE_MEMBERS \n"; | |
405 else if (isClassDeclaration()) | |
406 m = "$(DDOC_CLASS_MEMBERS \n"; | |
407 else if (isStructDeclaration()) | |
408 m = "$(DDOC_STRUCT_MEMBERS \n"; | |
409 else if (isEnumDeclaration()) | |
410 m = "$(DDOC_ENUM_MEMBERS \n"; | |
411 else if (isTemplateDeclaration()) | |
412 m = "$(DDOC_TEMPLATE_MEMBERS \n"; | |
413 | |
336 | 414 unsigned offset1 = buf->offset; // save starting offset |
159 | 415 buf->writestring(m); |
336 | 416 unsigned offset2 = buf->offset; // to see if we write anything |
159 | 417 sc = sc->push(this); |
418 for (int i = 0; i < members->dim; i++) | |
419 { | |
420 Dsymbol *s = (Dsymbol *)members->data[i]; | |
421 //printf("\ts = '%s'\n", s->toChars()); | |
422 s->emitComment(sc); | |
423 } | |
424 sc->pop(); | |
336 | 425 if (buf->offset == offset2) |
426 { | |
427 /* Didn't write out any members, so back out last write | |
428 */ | |
429 buf->offset = offset1; | |
430 } | |
431 else | |
432 buf->writestring(")\n"); | |
159 | 433 } |
434 } | |
435 | |
436 void emitProtection(OutBuffer *buf, PROT prot) | |
437 { | |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
571
diff
changeset
|
438 const char *p; |
159 | 439 |
440 switch (prot) | |
441 { | |
442 case PROTpackage: p = "package"; break; | |
443 case PROTprotected: p = "protected"; break; | |
444 case PROTexport: p = "export"; break; | |
445 default: p = NULL; break; | |
446 } | |
447 if (p) | |
448 buf->printf("%s ", p); | |
449 } | |
450 | |
451 void Dsymbol::emitComment(Scope *sc) { } | |
452 void InvariantDeclaration::emitComment(Scope *sc) { } | |
336 | 453 #if DMDV2 |
454 void PostBlitDeclaration::emitComment(Scope *sc) { } | |
455 #endif | |
159 | 456 void DtorDeclaration::emitComment(Scope *sc) { } |
457 void StaticCtorDeclaration::emitComment(Scope *sc) { } | |
458 void StaticDtorDeclaration::emitComment(Scope *sc) { } | |
459 void ClassInfoDeclaration::emitComment(Scope *sc) { } | |
460 void ModuleInfoDeclaration::emitComment(Scope *sc) { } | |
461 void TypeInfoDeclaration::emitComment(Scope *sc) { } | |
462 | |
463 | |
464 void Declaration::emitComment(Scope *sc) | |
465 { | |
466 //printf("Declaration::emitComment(%p '%s'), comment = '%s'\n", this, toChars(), comment); | |
467 //printf("type = %p\n", type); | |
468 | |
469 if (protection == PROTprivate || !ident || | |
470 (!type && !isCtorDeclaration() && !isAliasDeclaration())) | |
471 return; | |
472 if (!comment) | |
473 return; | |
474 | |
475 OutBuffer *buf = sc->docbuf; | |
476 DocComment *dc = DocComment::parse(sc, this, comment); | |
477 unsigned o; | |
478 | |
479 if (!dc) | |
480 { | |
481 emitDitto(sc); | |
482 return; | |
483 } | |
484 dc->pmacrotable = &sc->module->macrotable; | |
485 | |
486 buf->writestring(ddoc_decl_s); | |
487 o = buf->offset; | |
488 toDocBuffer(buf); | |
489 highlightCode(sc, this, buf, o); | |
490 sc->lastoffset = buf->offset; | |
491 buf->writestring(ddoc_decl_e); | |
492 | |
493 buf->writestring(ddoc_decl_dd_s); | |
494 dc->writeSections(sc, this, buf); | |
495 buf->writestring(ddoc_decl_dd_e); | |
496 } | |
497 | |
498 void AggregateDeclaration::emitComment(Scope *sc) | |
499 { | |
500 //printf("AggregateDeclaration::emitComment() '%s'\n", toChars()); | |
501 if (prot() == PROTprivate) | |
502 return; | |
503 if (!comment) | |
504 return; | |
505 | |
506 OutBuffer *buf = sc->docbuf; | |
507 DocComment *dc = DocComment::parse(sc, this, comment); | |
508 | |
509 if (!dc) | |
510 { | |
511 emitDitto(sc); | |
512 return; | |
513 } | |
514 dc->pmacrotable = &sc->module->macrotable; | |
515 | |
516 buf->writestring(ddoc_decl_s); | |
517 toDocBuffer(buf); | |
518 sc->lastoffset = buf->offset; | |
519 buf->writestring(ddoc_decl_e); | |
520 | |
521 buf->writestring(ddoc_decl_dd_s); | |
522 dc->writeSections(sc, this, buf); | |
523 emitMemberComments(sc); | |
524 buf->writestring(ddoc_decl_dd_e); | |
525 } | |
526 | |
527 void TemplateDeclaration::emitComment(Scope *sc) | |
528 { | |
529 //printf("TemplateDeclaration::emitComment() '%s', kind = %s\n", toChars(), kind()); | |
530 if (prot() == PROTprivate) | |
531 return; | |
532 | |
336 | 533 unsigned char *com = comment; |
159 | 534 int hasmembers = 1; |
535 | |
536 Dsymbol *ss = this; | |
537 | |
538 if (onemember) | |
539 { | |
540 ss = onemember->isAggregateDeclaration(); | |
541 if (!ss) | |
542 { | |
543 ss = onemember->isFuncDeclaration(); | |
544 if (ss) | |
336 | 545 { hasmembers = 0; |
546 if (com != ss->comment) | |
547 com = Lexer::combineComments(com, ss->comment); | |
548 } | |
159 | 549 else |
550 ss = this; | |
551 } | |
552 } | |
553 | |
336 | 554 if (!com) |
555 return; | |
556 | |
557 OutBuffer *buf = sc->docbuf; | |
558 DocComment *dc = DocComment::parse(sc, this, com); | |
559 unsigned o; | |
560 | |
159 | 561 if (!dc) |
562 { | |
563 ss->emitDitto(sc); | |
564 return; | |
565 } | |
566 dc->pmacrotable = &sc->module->macrotable; | |
567 | |
568 buf->writestring(ddoc_decl_s); | |
569 o = buf->offset; | |
570 ss->toDocBuffer(buf); | |
571 if (ss == this) | |
572 highlightCode(sc, this, buf, o); | |
573 sc->lastoffset = buf->offset; | |
574 buf->writestring(ddoc_decl_e); | |
575 | |
576 buf->writestring(ddoc_decl_dd_s); | |
577 dc->writeSections(sc, this, buf); | |
578 if (hasmembers) | |
579 ((ScopeDsymbol *)ss)->emitMemberComments(sc); | |
580 buf->writestring(ddoc_decl_dd_e); | |
581 } | |
582 | |
583 void EnumDeclaration::emitComment(Scope *sc) | |
584 { | |
585 if (prot() == PROTprivate) | |
586 return; | |
587 // if (!comment) | |
588 { if (isAnonymous() && members) | |
589 { | |
590 for (int i = 0; i < members->dim; i++) | |
591 { | |
592 Dsymbol *s = (Dsymbol *)members->data[i]; | |
593 s->emitComment(sc); | |
594 } | |
595 return; | |
596 } | |
597 } | |
598 if (!comment) | |
599 return; | |
600 if (isAnonymous()) | |
601 return; | |
602 | |
603 OutBuffer *buf = sc->docbuf; | |
604 DocComment *dc = DocComment::parse(sc, this, comment); | |
605 | |
606 if (!dc) | |
607 { | |
608 emitDitto(sc); | |
609 return; | |
610 } | |
611 dc->pmacrotable = &sc->module->macrotable; | |
612 | |
613 buf->writestring(ddoc_decl_s); | |
614 toDocBuffer(buf); | |
615 sc->lastoffset = buf->offset; | |
616 buf->writestring(ddoc_decl_e); | |
617 | |
618 buf->writestring(ddoc_decl_dd_s); | |
619 dc->writeSections(sc, this, buf); | |
620 emitMemberComments(sc); | |
621 buf->writestring(ddoc_decl_dd_e); | |
622 } | |
623 | |
624 void EnumMember::emitComment(Scope *sc) | |
625 { | |
626 //printf("EnumMember::emitComment(%p '%s'), comment = '%s'\n", this, toChars(), comment); | |
627 if (prot() == PROTprivate) | |
628 return; | |
629 if (!comment) | |
630 return; | |
631 | |
632 OutBuffer *buf = sc->docbuf; | |
633 DocComment *dc = DocComment::parse(sc, this, comment); | |
634 unsigned o; | |
635 | |
636 if (!dc) | |
637 { | |
638 emitDitto(sc); | |
639 return; | |
640 } | |
641 dc->pmacrotable = &sc->module->macrotable; | |
642 | |
643 buf->writestring(ddoc_decl_s); | |
644 o = buf->offset; | |
645 toDocBuffer(buf); | |
646 highlightCode(sc, this, buf, o); | |
647 sc->lastoffset = buf->offset; | |
648 buf->writestring(ddoc_decl_e); | |
649 | |
650 buf->writestring(ddoc_decl_dd_s); | |
651 dc->writeSections(sc, this, buf); | |
652 buf->writestring(ddoc_decl_dd_e); | |
653 } | |
654 | |
655 /******************************* toDocBuffer **********************************/ | |
656 | |
657 void Dsymbol::toDocBuffer(OutBuffer *buf) | |
658 { | |
659 //printf("Dsymbol::toDocbuffer() %s\n", toChars()); | |
660 HdrGenState hgs; | |
661 | |
662 hgs.ddoc = 1; | |
663 toCBuffer(buf, &hgs); | |
664 } | |
665 | |
666 void prefix(OutBuffer *buf, Dsymbol *s) | |
667 { | |
668 if (s->isDeprecated()) | |
669 buf->writestring("deprecated "); | |
670 Declaration *d = s->isDeclaration(); | |
671 if (d) | |
672 { | |
673 emitProtection(buf, d->protection); | |
674 if (d->isAbstract()) | |
675 buf->writestring("abstract "); | |
676 if (d->isStatic()) | |
677 buf->writestring("static "); | |
678 if (d->isConst()) | |
679 buf->writestring("const "); | |
336 | 680 #if DMDV2 |
1619
c61782a76dff
Merge DMD r304: refactor invariant => immutable
Leandro Lucarella <llucax@gmail.com>
parents:
1607
diff
changeset
|
681 if (d->isImmutable()) |
1587 | 682 buf->writestring("immutable "); |
159 | 683 #endif |
684 if (d->isFinal()) | |
685 buf->writestring("final "); | |
686 if (d->isSynchronized()) | |
687 buf->writestring("synchronized "); | |
688 } | |
689 } | |
690 | |
691 void Declaration::toDocBuffer(OutBuffer *buf) | |
692 { | |
693 //printf("Declaration::toDocbuffer() %s, originalType = %p\n", toChars(), originalType); | |
694 if (ident) | |
695 { | |
696 prefix(buf, this); | |
697 | |
698 if (type) | |
699 { HdrGenState hgs; | |
700 hgs.ddoc = 1; | |
701 if (originalType) | |
702 { //originalType->print(); | |
703 originalType->toCBuffer(buf, ident, &hgs); | |
704 } | |
705 else | |
706 type->toCBuffer(buf, ident, &hgs); | |
707 } | |
708 else | |
709 buf->writestring(ident->toChars()); | |
710 buf->writestring(";\n"); | |
711 } | |
712 } | |
713 | |
714 | |
715 void AliasDeclaration::toDocBuffer(OutBuffer *buf) | |
716 { | |
717 //printf("AliasDeclaration::toDocbuffer() %s\n", toChars()); | |
718 if (ident) | |
719 { | |
720 if (isDeprecated()) | |
721 buf->writestring("deprecated "); | |
722 | |
723 emitProtection(buf, protection); | |
724 buf->writestring("alias "); | |
725 buf->writestring(toChars()); | |
726 buf->writestring(";\n"); | |
727 } | |
728 } | |
729 | |
730 | |
731 void TypedefDeclaration::toDocBuffer(OutBuffer *buf) | |
732 { | |
733 if (ident) | |
734 { | |
735 if (isDeprecated()) | |
736 buf->writestring("deprecated "); | |
737 | |
738 emitProtection(buf, protection); | |
739 buf->writestring("typedef "); | |
740 buf->writestring(toChars()); | |
741 buf->writestring(";\n"); | |
742 } | |
743 } | |
744 | |
745 | |
746 void FuncDeclaration::toDocBuffer(OutBuffer *buf) | |
747 { | |
748 //printf("FuncDeclaration::toDocbuffer() %s\n", toChars()); | |
749 if (ident) | |
750 { | |
751 TemplateDeclaration *td; | |
752 | |
753 if (parent && | |
754 (td = parent->isTemplateDeclaration()) != NULL && | |
755 td->onemember == this) | |
336 | 756 { /* It's a function template |
757 */ | |
758 HdrGenState hgs; | |
159 | 759 unsigned o = buf->offset; |
760 TypeFunction *tf = (TypeFunction *)type; | |
761 | |
762 hgs.ddoc = 1; | |
763 prefix(buf, td); | |
764 tf->next->toCBuffer(buf, NULL, &hgs); | |
765 buf->writeByte(' '); | |
766 buf->writestring(ident->toChars()); | |
767 buf->writeByte('('); | |
768 for (int i = 0; i < td->origParameters->dim; i++) | |
769 { | |
770 TemplateParameter *tp = (TemplateParameter *)td->origParameters->data[i]; | |
771 if (i) | |
510
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
336
diff
changeset
|
772 buf->writestring(", "); |
159 | 773 tp->toCBuffer(buf, &hgs); |
774 } | |
775 buf->writeByte(')'); | |
1607
207a8a438dea
Merge DMD r253: refactor: Argument => Parameter
Leandro Lucarella <llucax@gmail.com>
parents:
1587
diff
changeset
|
776 Parameter::argsToCBuffer(buf, &hgs, tf->parameters, tf->varargs); |
159 | 777 buf->writestring(";\n"); |
778 | |
779 highlightCode(NULL, this, buf, o); | |
780 } | |
781 else | |
782 { | |
783 Declaration::toDocBuffer(buf); | |
784 } | |
785 } | |
786 } | |
787 | |
788 void CtorDeclaration::toDocBuffer(OutBuffer *buf) | |
789 { | |
790 HdrGenState hgs; | |
791 | |
792 buf->writestring("this"); | |
1607
207a8a438dea
Merge DMD r253: refactor: Argument => Parameter
Leandro Lucarella <llucax@gmail.com>
parents:
1587
diff
changeset
|
793 Parameter::argsToCBuffer(buf, &hgs, arguments, varargs); |
159 | 794 buf->writestring(";\n"); |
795 } | |
796 | |
797 | |
798 void AggregateDeclaration::toDocBuffer(OutBuffer *buf) | |
799 { | |
800 if (ident) | |
801 { | |
802 #if 0 | |
803 emitProtection(buf, protection); | |
804 #endif | |
805 buf->printf("%s $(DDOC_PSYMBOL %s)", kind(), toChars()); | |
806 buf->writestring(";\n"); | |
807 } | |
808 } | |
809 | |
810 void StructDeclaration::toDocBuffer(OutBuffer *buf) | |
811 { | |
812 //printf("StructDeclaration::toDocbuffer() %s\n", toChars()); | |
813 if (ident) | |
814 { | |
815 #if 0 | |
816 emitProtection(buf, protection); | |
817 #endif | |
818 TemplateDeclaration *td; | |
819 | |
820 if (parent && | |
821 (td = parent->isTemplateDeclaration()) != NULL && | |
822 td->onemember == this) | |
823 { unsigned o = buf->offset; | |
824 td->toDocBuffer(buf); | |
825 highlightCode(NULL, this, buf, o); | |
826 } | |
827 else | |
828 { | |
829 buf->printf("%s $(DDOC_PSYMBOL %s)", kind(), toChars()); | |
830 } | |
831 buf->writestring(";\n"); | |
832 } | |
833 } | |
834 | |
835 void ClassDeclaration::toDocBuffer(OutBuffer *buf) | |
836 { | |
837 //printf("ClassDeclaration::toDocbuffer() %s\n", toChars()); | |
838 if (ident) | |
839 { | |
840 #if 0 | |
841 emitProtection(buf, protection); | |
842 #endif | |
843 TemplateDeclaration *td; | |
844 | |
845 if (parent && | |
846 (td = parent->isTemplateDeclaration()) != NULL && | |
847 td->onemember == this) | |
848 { unsigned o = buf->offset; | |
849 td->toDocBuffer(buf); | |
850 highlightCode(NULL, this, buf, o); | |
851 } | |
852 else | |
853 { | |
876
27a379f288bf
Merged DMD 1.039
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
875
diff
changeset
|
854 if (isAbstract()) |
27a379f288bf
Merged DMD 1.039
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
875
diff
changeset
|
855 buf->writestring("abstract "); |
159 | 856 buf->printf("%s $(DDOC_PSYMBOL %s)", kind(), toChars()); |
857 } | |
858 int any = 0; | |
859 for (int i = 0; i < baseclasses.dim; i++) | |
860 { BaseClass *bc = (BaseClass *)baseclasses.data[i]; | |
861 | |
862 if (bc->protection == PROTprivate) | |
863 continue; | |
864 if (bc->base && bc->base->ident == Id::Object) | |
865 continue; | |
866 | |
867 if (any) | |
868 buf->writestring(", "); | |
869 else | |
870 { buf->writestring(": "); | |
871 any = 1; | |
872 } | |
873 emitProtection(buf, bc->protection); | |
874 if (bc->base) | |
875 { | |
876 buf->writestring(bc->base->toPrettyChars()); | |
877 } | |
878 else | |
879 { | |
880 HdrGenState hgs; | |
881 bc->type->toCBuffer(buf, NULL, &hgs); | |
882 } | |
883 } | |
884 buf->writestring(";\n"); | |
885 } | |
886 } | |
887 | |
888 | |
889 void EnumDeclaration::toDocBuffer(OutBuffer *buf) | |
890 { | |
891 if (ident) | |
892 { | |
893 buf->printf("%s $(DDOC_PSYMBOL %s)", kind(), toChars()); | |
894 buf->writestring(";\n"); | |
895 } | |
896 } | |
897 | |
898 void EnumMember::toDocBuffer(OutBuffer *buf) | |
899 { | |
900 if (ident) | |
901 { | |
902 buf->writestring(toChars()); | |
903 } | |
904 } | |
905 | |
906 | |
907 /********************************* DocComment *********************************/ | |
908 | |
909 DocComment::DocComment() | |
910 { | |
911 memset(this, 0, sizeof(DocComment)); | |
912 } | |
913 | |
914 DocComment *DocComment::parse(Scope *sc, Dsymbol *s, unsigned char *comment) | |
915 { unsigned idlen; | |
916 | |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
571
diff
changeset
|
917 //printf("parse(%s): '%s'\n", s->toChars(), comment); |
159 | 918 if (sc->lastdc && isDitto(comment)) |
919 return NULL; | |
920 | |
921 DocComment *dc = new DocComment(); | |
922 if (!comment) | |
923 return dc; | |
924 | |
925 dc->parseSections(comment); | |
926 | |
927 for (int i = 0; i < dc->sections.dim; i++) | |
928 { Section *s = (Section *)dc->sections.data[i]; | |
929 | |
930 if (icmp("copyright", s->name, s->namelen) == 0) | |
931 { | |
932 dc->copyright = s; | |
933 } | |
934 if (icmp("macros", s->name, s->namelen) == 0) | |
935 { | |
936 dc->macros = s; | |
937 } | |
938 } | |
939 | |
940 sc->lastdc = dc; | |
941 return dc; | |
942 } | |
943 | |
944 /***************************************** | |
945 * Parse next paragraph out of *pcomment. | |
946 * Update *pcomment to point past paragraph. | |
947 * Returns NULL if no more paragraphs. | |
948 * If paragraph ends in 'identifier:', | |
949 * then (*pcomment)[0 .. idlen] is the identifier. | |
950 */ | |
951 | |
952 void DocComment::parseSections(unsigned char *comment) | |
953 { unsigned char *p; | |
954 unsigned char *pstart; | |
955 unsigned char *pend; | |
956 unsigned char *idstart; | |
957 unsigned idlen; | |
958 | |
959 unsigned char *name = NULL; | |
960 unsigned namelen = 0; | |
961 | |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
571
diff
changeset
|
962 //printf("parseSections('%s')\n", comment); |
159 | 963 p = comment; |
964 while (*p) | |
965 { | |
966 p = skipwhitespace(p); | |
967 pstart = p; | |
968 | |
969 /* Find end of section, which is ended by one of: | |
1587 | 970 * 'identifier:' (but not inside a code section) |
159 | 971 * '\0' |
972 */ | |
973 idlen = 0; | |
1587 | 974 int inCode = 0; |
159 | 975 while (1) |
976 { | |
1587 | 977 // Check for start/end of a code section |
978 if (*p == '-') | |
159 | 979 { |
1587 | 980 int numdash = 0; |
981 while (*p == '-') | |
982 { | |
983 ++numdash; | |
984 p++; | |
985 } | |
986 // BUG: handle UTF PS and LS too | |
987 if (!*p || *p == '\r' || *p == '\n' && numdash >= 3) | |
988 inCode ^= 1; | |
989 } | |
990 | |
991 if (!inCode && isIdStart(p)) | |
992 { | |
993 unsigned char *q = p + utfStride(p); | |
994 while (isIdTail(q)) | |
995 q += utfStride(q); | |
159 | 996 if (*q == ':') // identifier: ends it |
997 { idlen = q - p; | |
998 idstart = p; | |
999 for (pend = p; pend > pstart; pend--) | |
1000 { if (pend[-1] == '\n') | |
1001 break; | |
1002 } | |
1003 p = q + 1; | |
1004 break; | |
1005 } | |
1006 } | |
1007 while (1) | |
1008 { | |
1009 if (!*p) | |
1010 { pend = p; | |
1011 goto L1; | |
1012 } | |
1013 if (*p == '\n') | |
1014 { p++; | |
1015 if (*p == '\n' && !summary && !namelen) | |
1016 { | |
1017 pend = p; | |
1018 p++; | |
1019 goto L1; | |
1020 } | |
1021 break; | |
1022 } | |
1023 p++; | |
1024 } | |
1025 p = skipwhitespace(p); | |
1026 } | |
1027 L1: | |
1028 | |
1029 if (namelen || pstart < pend) | |
1030 { | |
1031 Section *s; | |
1032 if (icmp("Params", name, namelen) == 0) | |
1033 s = new ParamSection(); | |
1034 else if (icmp("Macros", name, namelen) == 0) | |
1035 s = new MacroSection(); | |
1036 else | |
1037 s = new Section(); | |
1038 s->name = name; | |
1039 s->namelen = namelen; | |
1040 s->body = pstart; | |
1041 s->bodylen = pend - pstart; | |
1042 s->nooutput = 0; | |
1043 | |
1044 //printf("Section: '%.*s' = '%.*s'\n", s->namelen, s->name, s->bodylen, s->body); | |
1045 | |
1046 sections.push(s); | |
1047 | |
1048 if (!summary && !namelen) | |
1049 summary = s; | |
1050 } | |
1051 | |
1052 if (idlen) | |
1053 { name = idstart; | |
1054 namelen = idlen; | |
1055 } | |
1056 else | |
1057 { name = NULL; | |
1058 namelen = 0; | |
1059 if (!*p) | |
1060 break; | |
1061 } | |
1062 } | |
1063 } | |
1064 | |
1065 void DocComment::writeSections(Scope *sc, Dsymbol *s, OutBuffer *buf) | |
1066 { | |
1067 //printf("DocComment::writeSections()\n"); | |
1068 if (sections.dim) | |
1069 { | |
1070 buf->writestring("$(DDOC_SECTIONS \n"); | |
1071 for (int i = 0; i < sections.dim; i++) | |
1072 { Section *sec = (Section *)sections.data[i]; | |
1073 | |
1074 if (sec->nooutput) | |
1075 continue; | |
1076 //printf("Section: '%.*s' = '%.*s'\n", sec->namelen, sec->name, sec->bodylen, sec->body); | |
1077 if (sec->namelen || i) | |
1078 sec->write(this, sc, s, buf); | |
1079 else | |
1080 { | |
1081 buf->writestring("$(DDOC_SUMMARY "); | |
1082 unsigned o = buf->offset; | |
1083 buf->write(sec->body, sec->bodylen); | |
1084 highlightText(sc, s, buf, o); | |
1085 buf->writestring(")\n"); | |
1086 } | |
1087 } | |
1088 buf->writestring(")\n"); | |
1089 } | |
1090 else | |
1091 { | |
1092 buf->writestring("$(DDOC_BLANKLINE)\n"); | |
1093 } | |
1094 } | |
1095 | |
1096 /*************************************************** | |
1097 */ | |
1098 | |
1099 void Section::write(DocComment *dc, Scope *sc, Dsymbol *s, OutBuffer *buf) | |
1100 { | |
1101 if (namelen) | |
1102 { | |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
571
diff
changeset
|
1103 static const char *table[] = |
159 | 1104 { "AUTHORS", "BUGS", "COPYRIGHT", "DATE", |
1105 "DEPRECATED", "EXAMPLES", "HISTORY", "LICENSE", | |
1106 "RETURNS", "SEE_ALSO", "STANDARDS", "THROWS", | |
1107 "VERSION" }; | |
1108 | |
1109 for (int i = 0; i < sizeof(table) / sizeof(table[0]); i++) | |
1110 { | |
1111 if (icmp(table[i], name, namelen) == 0) | |
1112 { | |
1113 buf->printf("$(DDOC_%s ", table[i]); | |
1114 goto L1; | |
1115 } | |
1116 } | |
1117 | |
1118 buf->writestring("$(DDOC_SECTION "); | |
1119 // Replace _ characters with spaces | |
1120 buf->writestring("$(DDOC_SECTION_H "); | |
1121 for (unsigned u = 0; u < namelen; u++) | |
1122 { unsigned char c = name[u]; | |
1123 buf->writeByte((c == '_') ? ' ' : c); | |
1124 } | |
1125 buf->writestring(":)\n"); | |
1126 } | |
1127 else | |
1128 { | |
1129 buf->writestring("$(DDOC_DESCRIPTION "); | |
1130 } | |
1131 L1: | |
1132 unsigned o = buf->offset; | |
1133 buf->write(body, bodylen); | |
1134 highlightText(sc, s, buf, o); | |
1135 buf->writestring(")\n"); | |
1136 } | |
1137 | |
1138 /*************************************************** | |
1139 */ | |
1140 | |
1141 void ParamSection::write(DocComment *dc, Scope *sc, Dsymbol *s, OutBuffer *buf) | |
1142 { | |
1143 unsigned char *p = body; | |
1144 unsigned len = bodylen; | |
1145 unsigned char *pend = p + len; | |
1146 | |
1147 unsigned char *tempstart; | |
1148 unsigned templen; | |
1149 | |
1150 unsigned char *namestart; | |
1151 unsigned namelen = 0; // !=0 if line continuation | |
1152 | |
1153 unsigned char *textstart; | |
1154 unsigned textlen; | |
1155 | |
1156 unsigned o; | |
1607
207a8a438dea
Merge DMD r253: refactor: Argument => Parameter
Leandro Lucarella <llucax@gmail.com>
parents:
1587
diff
changeset
|
1157 Parameter *arg; |
159 | 1158 |
1159 buf->writestring("$(DDOC_PARAMS \n"); | |
1160 while (p < pend) | |
1161 { | |
1162 // Skip to start of macro | |
1587 | 1163 while (1) |
159 | 1164 { |
1165 switch (*p) | |
1166 { | |
1167 case ' ': | |
1168 case '\t': | |
1587 | 1169 p++; |
159 | 1170 continue; |
1171 | |
1172 case '\n': | |
1173 p++; | |
1174 goto Lcont; | |
1175 | |
1176 default: | |
1587 | 1177 if (isIdStart(p)) |
1178 break; | |
1179 if (namelen) | |
1180 goto Ltext; // continuation of prev macro | |
1181 goto Lskipline; | |
159 | 1182 } |
1183 break; | |
1184 } | |
1185 tempstart = p; | |
1186 | |
1587 | 1187 while (isIdTail(p)) |
1188 p += utfStride(p); | |
159 | 1189 templen = p - tempstart; |
1190 | |
1191 while (*p == ' ' || *p == '\t') | |
1192 p++; | |
1193 | |
1194 if (*p != '=') | |
1195 { if (namelen) | |
1196 goto Ltext; // continuation of prev macro | |
1197 goto Lskipline; | |
1198 } | |
1199 p++; | |
1200 | |
1201 if (namelen) | |
1202 { // Output existing param | |
1203 | |
1204 L1: | |
1205 //printf("param '%.*s' = '%.*s'\n", namelen, namestart, textlen, textstart); | |
1206 HdrGenState hgs; | |
1207 buf->writestring("$(DDOC_PARAM_ROW "); | |
1208 buf->writestring("$(DDOC_PARAM_ID "); | |
1209 o = buf->offset; | |
1210 arg = isFunctionParameter(s, namestart, namelen); | |
1211 if (arg && arg->type && arg->ident) | |
1212 arg->type->toCBuffer(buf, arg->ident, &hgs); | |
1213 else | |
1214 buf->write(namestart, namelen); | |
1215 highlightCode(sc, s, buf, o); | |
1216 buf->writestring(")\n"); | |
1217 | |
1218 buf->writestring("$(DDOC_PARAM_DESC "); | |
1219 o = buf->offset; | |
1220 buf->write(textstart, textlen); | |
1221 highlightText(sc, s, buf, o); | |
1222 buf->writestring(")"); | |
1223 buf->writestring(")\n"); | |
1224 namelen = 0; | |
1225 if (p >= pend) | |
1226 break; | |
1227 } | |
1228 | |
1229 namestart = tempstart; | |
1230 namelen = templen; | |
1231 | |
1232 while (*p == ' ' || *p == '\t') | |
1233 p++; | |
1234 textstart = p; | |
1235 | |
1236 Ltext: | |
1237 while (*p != '\n') | |
1238 p++; | |
1239 textlen = p - textstart; | |
1240 p++; | |
1241 | |
1242 Lcont: | |
1243 continue; | |
1244 | |
1245 Lskipline: | |
1246 // Ignore this line | |
1247 while (*p++ != '\n') | |
1248 ; | |
1249 } | |
1250 if (namelen) | |
1251 goto L1; // write out last one | |
1252 buf->writestring(")\n"); | |
1253 } | |
1254 | |
1255 /*************************************************** | |
1256 */ | |
1257 | |
1258 void MacroSection::write(DocComment *dc, Scope *sc, Dsymbol *s, OutBuffer *buf) | |
1259 { | |
1260 //printf("MacroSection::write()\n"); | |
1261 DocComment::parseMacros(dc->pescapetable, dc->pmacrotable, body, bodylen); | |
1262 } | |
1263 | |
1264 /************************************************ | |
1265 * Parse macros out of Macros: section. | |
1266 * Macros are of the form: | |
1267 * name1 = value1 | |
1268 * | |
1269 * name2 = value2 | |
1270 */ | |
1271 | |
1272 void DocComment::parseMacros(Escape **pescapetable, Macro **pmacrotable, unsigned char *m, unsigned mlen) | |
1273 { | |
1274 unsigned char *p = m; | |
1275 unsigned len = mlen; | |
1276 unsigned char *pend = p + len; | |
1277 | |
1278 unsigned char *tempstart; | |
1279 unsigned templen; | |
1280 | |
1281 unsigned char *namestart; | |
1282 unsigned namelen = 0; // !=0 if line continuation | |
1283 | |
1284 unsigned char *textstart; | |
1285 unsigned textlen; | |
1286 | |
1287 while (p < pend) | |
1288 { | |
1289 // Skip to start of macro | |
1587 | 1290 while (1) |
159 | 1291 { |
1292 if (p >= pend) | |
1293 goto Ldone; | |
1294 switch (*p) | |
1295 { | |
1296 case ' ': | |
1297 case '\t': | |
1587 | 1298 p++; |
159 | 1299 continue; |
1300 | |
1301 case '\n': | |
1302 p++; | |
1303 goto Lcont; | |
1304 | |
1305 default: | |
1587 | 1306 if (isIdStart(p)) |
1307 break; | |
1308 if (namelen) | |
1309 goto Ltext; // continuation of prev macro | |
1310 goto Lskipline; | |
159 | 1311 } |
1312 break; | |
1313 } | |
1314 tempstart = p; | |
1315 | |
1316 while (1) | |
1317 { | |
1318 if (p >= pend) | |
1319 goto Ldone; | |
1587 | 1320 if (!isIdTail(p)) |
159 | 1321 break; |
1587 | 1322 p += utfStride(p); |
159 | 1323 } |
1324 templen = p - tempstart; | |
1325 | |
1326 while (1) | |
1327 { | |
1328 if (p >= pend) | |
1329 goto Ldone; | |
1330 if (!(*p == ' ' || *p == '\t')) | |
1331 break; | |
1332 p++; | |
1333 } | |
1334 | |
1335 if (*p != '=') | |
1336 { if (namelen) | |
1337 goto Ltext; // continuation of prev macro | |
1338 goto Lskipline; | |
1339 } | |
1340 p++; | |
1341 if (p >= pend) | |
1342 goto Ldone; | |
1343 | |
1344 if (namelen) | |
1345 { // Output existing macro | |
1346 L1: | |
1347 //printf("macro '%.*s' = '%.*s'\n", namelen, namestart, textlen, textstart); | |
1348 if (icmp("ESCAPES", namestart, namelen) == 0) | |
1349 parseEscapes(pescapetable, textstart, textlen); | |
1350 else | |
1351 Macro::define(pmacrotable, namestart, namelen, textstart, textlen); | |
1352 namelen = 0; | |
1353 if (p >= pend) | |
1354 break; | |
1355 } | |
1356 | |
1357 namestart = tempstart; | |
1358 namelen = templen; | |
1359 | |
1360 while (p < pend && (*p == ' ' || *p == '\t')) | |
1361 p++; | |
1362 textstart = p; | |
1363 | |
1364 Ltext: | |
1365 while (p < pend && *p != '\n') | |
1366 p++; | |
1367 textlen = p - textstart; | |
1368 | |
1369 // Remove trailing \r if there is one | |
1370 if (p > m && p[-1] == '\r') | |
1371 textlen--; | |
1372 | |
1373 p++; | |
1374 //printf("p = %p, pend = %p\n", p, pend); | |
1375 | |
1376 Lcont: | |
1377 continue; | |
1378 | |
1379 Lskipline: | |
1380 // Ignore this line | |
1381 while (p < pend && *p++ != '\n') | |
1382 ; | |
1383 } | |
1384 Ldone: | |
1385 if (namelen) | |
1386 goto L1; // write out last one | |
1387 } | |
1388 | |
1389 /************************************** | |
1390 * Parse escapes of the form: | |
1391 * /c/string/ | |
1392 * where c is a single character. | |
1393 * Multiple escapes can be separated | |
1394 * by whitespace and/or commas. | |
1395 */ | |
1396 | |
1397 void DocComment::parseEscapes(Escape **pescapetable, unsigned char *textstart, unsigned textlen) | |
1398 { Escape *escapetable = *pescapetable; | |
1399 | |
1400 if (!escapetable) | |
1401 { escapetable = new Escape; | |
1402 *pescapetable = escapetable; | |
1403 } | |
1404 unsigned char *p = textstart; | |
1405 unsigned char *pend = p + textlen; | |
1406 | |
1407 while (1) | |
1408 { | |
1409 while (1) | |
1410 { | |
1411 if (p + 4 >= pend) | |
1412 return; | |
1413 if (!(*p == ' ' || *p == '\t' || *p == '\n' || *p == ',')) | |
1414 break; | |
1415 p++; | |
1416 } | |
1417 if (p[0] != '/' || p[2] != '/') | |
1418 return; | |
1419 unsigned char c = p[1]; | |
1420 p += 3; | |
1421 unsigned char *start = p; | |
1422 while (1) | |
1423 { | |
1424 if (p >= pend) | |
1425 return; | |
1426 if (*p == '/') | |
1427 break; | |
1428 p++; | |
1429 } | |
1430 size_t len = p - start; | |
1431 char *s = (char *)memcpy(mem.malloc(len + 1), start, len); | |
1432 s[len] = 0; | |
1433 escapetable->strings[c] = s; | |
1434 //printf("%c = '%s'\n", c, s); | |
1435 p++; | |
1436 } | |
1437 } | |
1438 | |
1439 | |
1440 /****************************************** | |
1441 * Compare 0-terminated string with length terminated string. | |
1442 * Return < 0, ==0, > 0 | |
1443 */ | |
1444 | |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
571
diff
changeset
|
1445 int cmp(const char *stringz, void *s, size_t slen) |
159 | 1446 { |
1447 size_t len1 = strlen(stringz); | |
1448 | |
1449 if (len1 != slen) | |
1450 return len1 - slen; | |
1451 return memcmp(stringz, s, slen); | |
1452 } | |
1453 | |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
571
diff
changeset
|
1454 int icmp(const char *stringz, void *s, size_t slen) |
159 | 1455 { |
1456 size_t len1 = strlen(stringz); | |
1457 | |
1458 if (len1 != slen) | |
1459 return len1 - slen; | |
1460 return memicmp(stringz, (char *)s, slen); | |
1461 } | |
1462 | |
1463 /***************************************** | |
1464 * Return !=0 if comment consists entirely of "ditto". | |
1465 */ | |
1466 | |
1467 int isDitto(unsigned char *comment) | |
1468 { | |
1469 if (comment) | |
1470 { | |
1471 unsigned char *p = skipwhitespace(comment); | |
1472 | |
1473 if (memicmp((char *)p, "ditto", 5) == 0 && *skipwhitespace(p + 5) == 0) | |
1474 return 1; | |
1475 } | |
1476 return 0; | |
1477 } | |
1478 | |
1479 /********************************************** | |
1480 * Skip white space. | |
1481 */ | |
1482 | |
1483 unsigned char *skipwhitespace(unsigned char *p) | |
1484 { | |
1485 for (; 1; p++) | |
1486 { switch (*p) | |
1487 { | |
1488 case ' ': | |
1489 case '\t': | |
1490 case '\n': | |
1491 continue; | |
1492 } | |
1493 break; | |
1494 } | |
1495 return p; | |
1496 } | |
1497 | |
1498 | |
1499 /************************************************ | |
1500 * Scan forward to one of: | |
1501 * start of identifier | |
1502 * beginning of next line | |
1503 * end of buf | |
1504 */ | |
1505 | |
1587 | 1506 unsigned skiptoident(OutBuffer *buf, size_t i) |
159 | 1507 { |
1587 | 1508 while (i < buf->offset) |
1509 { dchar_t c; | |
1510 | |
1511 size_t oi = i; | |
1512 if (utf_decodeChar((unsigned char *)buf->data, buf->offset, &i, &c)) | |
1513 /* Ignore UTF errors, but still consume input | |
1514 */ | |
159 | 1515 break; |
1587 | 1516 if (c >= 0x80) |
1517 { | |
1518 if (!isUniAlpha(c)) | |
1519 continue; | |
1520 } | |
1521 else if (!(isalpha(c) || c == '_' || c == '\n')) | |
1522 continue; | |
1523 i = oi; | |
1524 break; | |
159 | 1525 } |
1526 return i; | |
1527 } | |
1528 | |
1529 /************************************************ | |
1530 * Scan forward past end of identifier. | |
1531 */ | |
1532 | |
1587 | 1533 unsigned skippastident(OutBuffer *buf, size_t i) |
159 | 1534 { |
1587 | 1535 while (i < buf->offset) |
1536 { dchar_t c; | |
1537 | |
1538 size_t oi = i; | |
1539 if (utf_decodeChar((unsigned char *)buf->data, buf->offset, &i, &c)) | |
1540 /* Ignore UTF errors, but still consume input | |
1541 */ | |
159 | 1542 break; |
1587 | 1543 if (c >= 0x80) |
1544 { | |
1545 if (isUniAlpha(c)) | |
1546 continue; | |
1547 } | |
1548 else if (isalnum(c) || c == '_') | |
1549 continue; | |
1550 i = oi; | |
1551 break; | |
159 | 1552 } |
1553 return i; | |
1554 } | |
1555 | |
1556 | |
1557 /************************************************ | |
1558 * Scan forward past URL starting at i. | |
1559 * We don't want to highlight parts of a URL. | |
1560 * Returns: | |
1561 * i if not a URL | |
1562 * index just past it if it is a URL | |
1563 */ | |
1564 | |
1587 | 1565 unsigned skippastURL(OutBuffer *buf, size_t i) |
159 | 1566 { unsigned length = buf->offset - i; |
1567 unsigned char *p = &buf->data[i]; | |
1568 unsigned j; | |
1569 unsigned sawdot = 0; | |
1570 | |
1571 if (length > 7 && memicmp((char *)p, "http://", 7) == 0) | |
1572 { | |
1573 j = 7; | |
1574 } | |
1575 else if (length > 8 && memicmp((char *)p, "https://", 8) == 0) | |
1576 { | |
1577 j = 8; | |
1578 } | |
1579 else | |
1580 goto Lno; | |
1581 | |
1582 for (; j < length; j++) | |
1583 { unsigned char c = p[j]; | |
1584 if (isalnum(c)) | |
1585 continue; | |
1586 if (c == '-' || c == '_' || c == '?' || | |
1587 c == '=' || c == '%' || c == '&' || | |
1588 c == '/' || c == '+' || c == '#' || | |
1589 c == '~') | |
1590 continue; | |
1591 if (c == '.') | |
1592 { | |
1593 sawdot = 1; | |
1594 continue; | |
1595 } | |
1596 break; | |
1597 } | |
1598 if (sawdot) | |
1599 return i + j; | |
1600 | |
1601 Lno: | |
1602 return i; | |
1603 } | |
1604 | |
1605 | |
1606 /**************************************************** | |
1607 */ | |
1608 | |
1609 int isKeyword(unsigned char *p, unsigned len) | |
1610 { | |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
571
diff
changeset
|
1611 static const char *table[] = { "true", "false", "null" }; |
159 | 1612 |
1613 for (int i = 0; i < sizeof(table) / sizeof(table[0]); i++) | |
1614 { | |
1615 if (cmp(table[i], p, len) == 0) | |
1616 return 1; | |
1617 } | |
1618 return 0; | |
1619 } | |
1620 | |
1621 /**************************************************** | |
1622 */ | |
1623 | |
1607
207a8a438dea
Merge DMD r253: refactor: Argument => Parameter
Leandro Lucarella <llucax@gmail.com>
parents:
1587
diff
changeset
|
1624 Parameter *isFunctionParameter(Dsymbol *s, unsigned char *p, unsigned len) |
159 | 1625 { |
1626 FuncDeclaration *f = s->isFuncDeclaration(); | |
1627 | |
1628 /* f->type may be NULL for template members. | |
1629 */ | |
1630 if (f && f->type) | |
1631 { | |
336 | 1632 TypeFunction *tf; |
1633 if (f->originalType) | |
1634 { | |
1635 tf = (TypeFunction *)f->originalType; | |
1636 } | |
1637 else | |
1638 tf = (TypeFunction *)f->type; | |
159 | 1639 |
1640 if (tf->parameters) | |
1641 { | |
1642 for (size_t k = 0; k < tf->parameters->dim; k++) | |
1607
207a8a438dea
Merge DMD r253: refactor: Argument => Parameter
Leandro Lucarella <llucax@gmail.com>
parents:
1587
diff
changeset
|
1643 { Parameter *arg = (Parameter *)tf->parameters->data[k]; |
159 | 1644 |
1645 if (arg->ident && cmp(arg->ident->toChars(), p, len) == 0) | |
1646 { | |
1647 return arg; | |
1648 } | |
1649 } | |
1650 } | |
1651 } | |
1652 return NULL; | |
1653 } | |
1654 | |
1655 /************************************************** | |
1656 * Highlight text section. | |
1657 */ | |
1658 | |
1659 void highlightText(Scope *sc, Dsymbol *s, OutBuffer *buf, unsigned offset) | |
1660 { | |
1661 //printf("highlightText()\n"); | |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
571
diff
changeset
|
1662 const char *sid = s->ident->toChars(); |
159 | 1663 FuncDeclaration *f = s->isFuncDeclaration(); |
1664 unsigned char *p; | |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
571
diff
changeset
|
1665 const char *se; |
159 | 1666 |
1667 int leadingBlank = 1; | |
1668 int inCode = 0; | |
1669 int inComment = 0; // in <!-- ... --> comment | |
1670 unsigned iCodeStart; // start of code section | |
1671 | |
1672 unsigned iLineStart = offset; | |
1673 | |
1674 for (unsigned i = offset; i < buf->offset; i++) | |
1675 { unsigned char c = buf->data[i]; | |
1676 | |
1677 Lcont: | |
1678 switch (c) | |
1679 { | |
1680 case ' ': | |
1681 case '\t': | |
1682 break; | |
1683 | |
1684 case '\n': | |
1685 if (sc && !inCode && i == iLineStart && i + 1 < buf->offset) // if "\n\n" | |
1686 { | |
1687 static char blankline[] = "$(DDOC_BLANKLINE)\n"; | |
1688 | |
1689 i = buf->insert(i, blankline, sizeof(blankline) - 1); | |
1690 } | |
1691 leadingBlank = 1; | |
1692 iLineStart = i + 1; | |
1693 break; | |
1694 | |
1695 case '<': | |
1696 leadingBlank = 0; | |
1697 if (inCode) | |
1698 break; | |
1699 p = &buf->data[i]; | |
1700 | |
1701 // Skip over comments | |
1702 if (p[1] == '!' && p[2] == '-' && p[3] == '-') | |
1703 { unsigned j = i + 4; | |
1704 p += 4; | |
1705 while (1) | |
1706 { | |
1707 if (j == buf->offset) | |
1708 goto L1; | |
1709 if (p[0] == '-' && p[1] == '-' && p[2] == '>') | |
1710 { | |
1711 i = j + 2; // place on closing '>' | |
1712 break; | |
1713 } | |
1714 j++; | |
1715 p++; | |
1716 } | |
1717 break; | |
1718 } | |
1719 | |
1720 // Skip over HTML tag | |
1721 if (isalpha(p[1]) || (p[1] == '/' && isalpha(p[2]))) | |
1722 { unsigned j = i + 2; | |
1723 p += 2; | |
1724 while (1) | |
1725 { | |
1726 if (j == buf->offset) | |
1727 goto L1; | |
1728 if (p[0] == '>') | |
1729 { | |
1730 i = j; // place on closing '>' | |
1731 break; | |
1732 } | |
1733 j++; | |
1734 p++; | |
1735 } | |
1736 break; | |
1737 } | |
1738 | |
1739 L1: | |
1740 // Replace '<' with '<' character entity | |
1741 se = Escape::escapeChar('<'); | |
1742 if (se) | |
1743 { size_t len = strlen(se); | |
1744 buf->remove(i, 1); | |
1745 i = buf->insert(i, se, len); | |
1746 i--; // point to ';' | |
1747 } | |
1748 break; | |
1749 | |
1750 case '>': | |
1751 leadingBlank = 0; | |
1752 if (inCode) | |
1753 break; | |
1754 // Replace '>' with '>' character entity | |
1755 se = Escape::escapeChar('>'); | |
1756 if (se) | |
1757 { size_t len = strlen(se); | |
1758 buf->remove(i, 1); | |
1759 i = buf->insert(i, se, len); | |
1760 i--; // point to ';' | |
1761 } | |
1762 break; | |
1763 | |
1764 case '&': | |
1765 leadingBlank = 0; | |
1766 if (inCode) | |
1767 break; | |
1768 p = &buf->data[i]; | |
1769 if (p[1] == '#' || isalpha(p[1])) | |
1770 break; // already a character entity | |
1771 // Replace '&' with '&' character entity | |
1772 se = Escape::escapeChar('&'); | |
1773 if (se) | |
1774 { size_t len = strlen(se); | |
1775 buf->remove(i, 1); | |
1776 i = buf->insert(i, se, len); | |
1777 i--; // point to ';' | |
1778 } | |
1779 break; | |
1780 | |
1781 case '-': | |
1782 /* A line beginning with --- delimits a code section. | |
1783 * inCode tells us if it is start or end of a code section. | |
1784 */ | |
1785 if (leadingBlank) | |
1786 { int istart = i; | |
1787 int eollen = 0; | |
1788 | |
1789 leadingBlank = 0; | |
1790 while (1) | |
1791 { | |
1792 ++i; | |
1793 if (i >= buf->offset) | |
1794 break; | |
1795 c = buf->data[i]; | |
1796 if (c == '\n') | |
1797 { eollen = 1; | |
1798 break; | |
1799 } | |
1800 if (c == '\r') | |
1801 { | |
1802 eollen = 1; | |
1803 if (i + 1 >= buf->offset) | |
1804 break; | |
1805 if (buf->data[i + 1] == '\n') | |
1806 { eollen = 2; | |
1807 break; | |
1808 } | |
1809 } | |
1810 // BUG: handle UTF PS and LS too | |
1811 if (c != '-') | |
1812 goto Lcont; | |
1813 } | |
1814 if (i - istart < 3) | |
1815 goto Lcont; | |
1816 | |
1817 // We have the start/end of a code section | |
1818 | |
1819 // Remove the entire --- line, including blanks and \n | |
1820 buf->remove(iLineStart, i - iLineStart + eollen); | |
1821 i = iLineStart; | |
1822 | |
1823 if (inCode) | |
1824 { | |
1825 inCode = 0; | |
1826 // The code section is from iCodeStart to i | |
1827 OutBuffer codebuf; | |
1828 | |
1829 codebuf.write(buf->data + iCodeStart, i - iCodeStart); | |
1830 codebuf.writeByte(0); | |
1831 highlightCode2(sc, s, &codebuf, 0); | |
1832 buf->remove(iCodeStart, i - iCodeStart); | |
1833 i = buf->insert(iCodeStart, codebuf.data, codebuf.offset); | |
1834 i = buf->insert(i, ")\n", 2); | |
1835 i--; | |
1836 } | |
1837 else | |
1838 { static char pre[] = "$(D_CODE \n"; | |
1839 | |
1840 inCode = 1; | |
1841 i = buf->insert(i, pre, sizeof(pre) - 1); | |
1842 iCodeStart = i; | |
1843 i--; // place i on > | |
1844 } | |
1845 } | |
1846 break; | |
1847 | |
1848 default: | |
1849 leadingBlank = 0; | |
1587 | 1850 if (sc && !inCode && isIdStart(&buf->data[i])) |
159 | 1851 { unsigned j; |
1852 | |
1853 j = skippastident(buf, i); | |
1854 if (j > i) | |
1855 { | |
1856 unsigned k = skippastURL(buf, i); | |
1857 if (k > i) | |
1858 { i = k - 1; | |
1859 break; | |
1860 } | |
1861 | |
1862 if (buf->data[i] == '_') // leading '_' means no highlight | |
1863 { | |
1864 buf->remove(i, 1); | |
1865 i = j - 1; | |
1866 } | |
1867 else | |
1868 { | |
1869 if (cmp(sid, buf->data + i, j - i) == 0) | |
1870 { | |
1871 i = buf->bracket(i, "$(DDOC_PSYMBOL ", j, ")") - 1; | |
1872 break; | |
1873 } | |
1874 else if (isKeyword(buf->data + i, j - i)) | |
1875 { | |
1876 i = buf->bracket(i, "$(DDOC_KEYWORD ", j, ")") - 1; | |
1877 break; | |
1878 } | |
1879 else | |
1880 { | |
1881 if (f && isFunctionParameter(f, buf->data + i, j - i)) | |
1882 { | |
1883 //printf("highlighting arg '%s', i = %d, j = %d\n", arg->ident->toChars(), i, j); | |
1884 i = buf->bracket(i, "$(DDOC_PARAM ", j, ")") - 1; | |
1885 break; | |
1886 } | |
1887 } | |
1888 i = j - 1; | |
1889 } | |
1890 } | |
1891 } | |
1892 break; | |
1893 } | |
1894 } | |
1895 Ldone: | |
1896 ; | |
1897 } | |
1898 | |
1899 /************************************************** | |
1900 * Highlight code for DDOC section. | |
1901 */ | |
1902 | |
1903 void highlightCode(Scope *sc, Dsymbol *s, OutBuffer *buf, unsigned offset) | |
1904 { | |
1905 char *sid = s->ident->toChars(); | |
1906 FuncDeclaration *f = s->isFuncDeclaration(); | |
1907 | |
1908 //printf("highlightCode(s = '%s', kind = %s)\n", sid, s->kind()); | |
1909 for (unsigned i = offset; i < buf->offset; i++) | |
1910 { unsigned char c = buf->data[i]; | |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
571
diff
changeset
|
1911 const char *se; |
159 | 1912 |
1913 se = Escape::escapeChar(c); | |
1914 if (se) | |
1915 { | |
1916 size_t len = strlen(se); | |
1917 buf->remove(i, 1); | |
1918 i = buf->insert(i, se, len); | |
1919 i--; // point to ';' | |
1920 } | |
1587 | 1921 else if (isIdStart(&buf->data[i])) |
159 | 1922 { unsigned j; |
1923 | |
1924 j = skippastident(buf, i); | |
1925 if (j > i) | |
1926 { | |
1927 if (cmp(sid, buf->data + i, j - i) == 0) | |
1928 { | |
1929 i = buf->bracket(i, "$(DDOC_PSYMBOL ", j, ")") - 1; | |
1930 continue; | |
1931 } | |
1932 else if (f) | |
1933 { | |
1934 if (isFunctionParameter(f, buf->data + i, j - i)) | |
1935 { | |
1936 //printf("highlighting arg '%s', i = %d, j = %d\n", arg->ident->toChars(), i, j); | |
1937 i = buf->bracket(i, "$(DDOC_PARAM ", j, ")") - 1; | |
1938 continue; | |
1939 } | |
1940 } | |
1941 i = j - 1; | |
1942 } | |
1943 } | |
1944 } | |
1945 } | |
1946 | |
1947 /**************************************** | |
1948 */ | |
1949 | |
1950 void highlightCode3(OutBuffer *buf, unsigned char *p, unsigned char *pend) | |
1951 { | |
1952 for (; p < pend; p++) | |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
571
diff
changeset
|
1953 { const char *s = Escape::escapeChar(*p); |
159 | 1954 if (s) |
1955 buf->writestring(s); | |
1956 else | |
1957 buf->writeByte(*p); | |
1958 } | |
1959 } | |
1960 | |
1961 /************************************************** | |
1962 * Highlight code for CODE section. | |
1963 */ | |
1964 | |
1965 | |
1966 void highlightCode2(Scope *sc, Dsymbol *s, OutBuffer *buf, unsigned offset) | |
1967 { | |
1968 char *sid = s->ident->toChars(); | |
1969 FuncDeclaration *f = s->isFuncDeclaration(); | |
1970 unsigned errorsave = global.errors; | |
1971 Lexer lex(NULL, buf->data, 0, buf->offset - 1, 0, 1); | |
1972 Token tok; | |
1973 OutBuffer res; | |
1974 unsigned char *lastp = buf->data; | |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
571
diff
changeset
|
1975 const char *highlight; |
159 | 1976 |
1977 //printf("highlightCode2('%.*s')\n", buf->offset - 1, buf->data); | |
1978 res.reserve(buf->offset); | |
1979 while (1) | |
1980 { | |
1981 lex.scan(&tok); | |
1982 highlightCode3(&res, lastp, tok.ptr); | |
1983 highlight = NULL; | |
1984 switch (tok.value) | |
1985 { | |
1986 case TOKidentifier: | |
1987 if (!sc) | |
1988 break; | |
1989 if (cmp(sid, tok.ptr, lex.p - tok.ptr) == 0) | |
1990 { | |
1991 highlight = "$(D_PSYMBOL "; | |
1992 break; | |
1993 } | |
1994 else if (f) | |
1995 { | |
1996 if (isFunctionParameter(f, tok.ptr, lex.p - tok.ptr)) | |
1997 { | |
1998 //printf("highlighting arg '%s', i = %d, j = %d\n", arg->ident->toChars(), i, j); | |
1999 highlight = "$(D_PARAM "; | |
2000 break; | |
2001 } | |
2002 } | |
2003 break; | |
2004 | |
2005 case TOKcomment: | |
2006 highlight = "$(D_COMMENT "; | |
2007 break; | |
2008 | |
2009 case TOKstring: | |
2010 highlight = "$(D_STRING "; | |
2011 break; | |
2012 | |
2013 default: | |
2014 if (tok.isKeyword()) | |
2015 highlight = "$(D_KEYWORD "; | |
2016 break; | |
2017 } | |
2018 if (highlight) | |
2019 res.writestring(highlight); | |
2020 highlightCode3(&res, tok.ptr, lex.p); | |
2021 if (highlight) | |
2022 res.writeByte(')'); | |
2023 if (tok.value == TOKeof) | |
2024 break; | |
2025 lastp = lex.p; | |
2026 } | |
2027 buf->setsize(offset); | |
2028 buf->write(&res); | |
2029 global.errors = errorsave; | |
2030 } | |
2031 | |
2032 /*************************************** | |
2033 * Find character string to replace c with. | |
2034 */ | |
2035 | |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
571
diff
changeset
|
2036 const char *Escape::escapeChar(unsigned c) |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
571
diff
changeset
|
2037 { const char *s; |
159 | 2038 |
2039 switch (c) | |
2040 { | |
2041 case '<': | |
2042 s = "<"; | |
2043 break; | |
2044 case '>': | |
2045 s = ">"; | |
2046 break; | |
2047 case '&': | |
2048 s = "&"; | |
2049 break; | |
2050 default: | |
2051 s = NULL; | |
2052 break; | |
2053 } | |
2054 return s; | |
2055 } | |
2056 | |
1587 | 2057 /**************************************** |
2058 * Determine if p points to the start of an identifier. | |
2059 */ | |
2060 | |
2061 int isIdStart(unsigned char *p) | |
2062 { | |
2063 unsigned c = *p; | |
2064 if (isalpha(c) || c == '_') | |
2065 return 1; | |
2066 if (c >= 0x80) | |
2067 { size_t i = 0; | |
2068 if (utf_decodeChar(p, 4, &i, &c)) | |
2069 return 0; // ignore errors | |
2070 if (isUniAlpha(c)) | |
2071 return 1; | |
2072 } | |
2073 return 0; | |
2074 } | |
2075 | |
2076 /**************************************** | |
2077 * Determine if p points to the rest of an identifier. | |
2078 */ | |
2079 | |
2080 int isIdTail(unsigned char *p) | |
2081 { | |
2082 unsigned c = *p; | |
2083 if (isalnum(c) || c == '_') | |
2084 return 1; | |
2085 if (c >= 0x80) | |
2086 { size_t i = 0; | |
2087 if (utf_decodeChar(p, 4, &i, &c)) | |
2088 return 0; // ignore errors | |
2089 if (isUniAlpha(c)) | |
2090 return 1; | |
2091 } | |
2092 return 0; | |
2093 } | |
2094 | |
2095 /***************************************** | |
2096 * Return number of bytes in UTF character. | |
2097 */ | |
2098 | |
2099 int utfStride(unsigned char *p) | |
2100 { | |
2101 unsigned c = *p; | |
2102 if (c < 0x80) | |
2103 return 1; | |
2104 size_t i = 0; | |
2105 utf_decodeChar(p, 4, &i, &c); // ignore errors, but still consume input | |
2106 return i; | |
2107 } |