Mercurial > projects > ldc
annotate dmd/doc.c @ 1103:b30fe7e1dbb9
- Updated to DMD frontend 1.041.
- Removed dmd/inifile.c , it's not under a free license, replaced with libconfig based config file.
author | Tomas Lindquist Olsen <tomas.l.olsen gmail.com> |
---|---|
date | Thu, 12 Mar 2009 20:37:27 +0100 |
parents | 27a379f288bf |
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 |