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