Mercurial > projects > ldc
annotate dmd/doc.c @ 1308:316e9ecfeb7d
Automated merge with http://hg.dsource.org/projects/ldc
author | Frits van Bommel <fvbommel wxs.nl> |
---|---|
date | Wed, 06 May 2009 20:29:27 +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 |