annotate dmd/doc.c @ 876:27a379f288bf

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