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