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