Mercurial > projects > ldc
comparison dmd/doc.c @ 1587:def7a1d494fd
Merge DMD 1.051
author | Christian Kamm <kamm incasoftware de> |
---|---|
date | Fri, 06 Nov 2009 23:58:01 +0100 |
parents | eeb8b95ea92e |
children | 207a8a438dea |
comparison
equal
deleted
inserted
replaced
1586:7f728c52e63c | 1587:def7a1d494fd |
---|---|
1 | 1 |
2 // Compiler implementation of the D programming language | 2 // Compiler implementation of the D programming language |
3 // Copyright (c) 1999-2008 by Digital Mars | 3 // Copyright (c) 1999-2009 by Digital Mars |
4 // All Rights Reserved | 4 // All Rights Reserved |
5 // written by Walter Bright | 5 // written by Walter Bright |
6 // http://www.digitalmars.com | 6 // http://www.digitalmars.com |
7 // License for redistribution is by either the Artistic License | 7 // License for redistribution is by either the Artistic License |
8 // in artistic.txt, or the GNU General Public License in gnu.txt. | 8 // in artistic.txt, or the GNU General Public License in gnu.txt. |
31 #include "module.h" | 31 #include "module.h" |
32 #include "scope.h" | 32 #include "scope.h" |
33 #include "hdrgen.h" | 33 #include "hdrgen.h" |
34 #include "doc.h" | 34 #include "doc.h" |
35 #include "mtype.h" | 35 #include "mtype.h" |
36 #include "utf.h" | |
36 | 37 |
37 struct Escape | 38 struct Escape |
38 { | 39 { |
39 const char *strings[256]; | 40 const char *strings[256]; |
40 | 41 |
87 | 88 |
88 int cmp(const char *stringz, void *s, size_t slen); | 89 int cmp(const char *stringz, void *s, size_t slen); |
89 int icmp(const char *stringz, void *s, size_t slen); | 90 int icmp(const char *stringz, void *s, size_t slen); |
90 int isDitto(unsigned char *comment); | 91 int isDitto(unsigned char *comment); |
91 unsigned char *skipwhitespace(unsigned char *p); | 92 unsigned char *skipwhitespace(unsigned char *p); |
92 unsigned skiptoident(OutBuffer *buf, unsigned i); | 93 unsigned skiptoident(OutBuffer *buf, size_t i); |
93 unsigned skippastident(OutBuffer *buf, unsigned i); | 94 unsigned skippastident(OutBuffer *buf, size_t i); |
94 unsigned skippastURL(OutBuffer *buf, unsigned i); | 95 unsigned skippastURL(OutBuffer *buf, size_t i); |
95 void highlightText(Scope *sc, Dsymbol *s, OutBuffer *buf, unsigned offset); | 96 void highlightText(Scope *sc, Dsymbol *s, OutBuffer *buf, unsigned offset); |
96 void highlightCode(Scope *sc, Dsymbol *s, OutBuffer *buf, unsigned offset); | 97 void highlightCode(Scope *sc, Dsymbol *s, OutBuffer *buf, unsigned offset); |
97 void highlightCode2(Scope *sc, Dsymbol *s, OutBuffer *buf, unsigned offset); | 98 void highlightCode2(Scope *sc, Dsymbol *s, OutBuffer *buf, unsigned offset); |
98 Argument *isFunctionParameter(Dsymbol *s, unsigned char *p, unsigned len); | 99 Argument *isFunctionParameter(Dsymbol *s, unsigned char *p, unsigned len); |
100 | |
101 int isIdStart(unsigned char *p); | |
102 int isIdTail(unsigned char *p); | |
103 int utfStride(unsigned char *p); | |
99 | 104 |
100 static unsigned char ddoc_default[] = "\ | 105 static unsigned char ddoc_default[] = "\ |
101 DDOC = <html><head>\n\ | 106 DDOC = <html><head>\n\ |
102 <META http-equiv=\"content-type\" content=\"text/html; charset=utf-8\">\n\ | 107 <META http-equiv=\"content-type\" content=\"text/html; charset=utf-8\">\n\ |
103 <title>$(TITLE)</title>\n\ | 108 <title>$(TITLE)</title>\n\ |
236 dc->pescapetable = &escapetable; | 241 dc->pescapetable = &escapetable; |
237 | 242 |
238 // Generate predefined macros | 243 // Generate predefined macros |
239 | 244 |
240 // Set the title to be the name of the module | 245 // Set the title to be the name of the module |
241 { char *p = toPrettyChars(); | 246 { const char *p = toPrettyChars(); |
242 Macro::define(¯otable, (unsigned char *)"TITLE", 5, (unsigned char *)p, strlen(p)); | 247 Macro::define(¯otable, (unsigned char *)"TITLE", 5, (unsigned char *)p, strlen(p)); |
243 } | 248 } |
244 | 249 |
245 time_t t; | 250 time_t t; |
246 time(&t); | 251 time(&t); |
672 buf->writestring("static "); | 677 buf->writestring("static "); |
673 if (d->isConst()) | 678 if (d->isConst()) |
674 buf->writestring("const "); | 679 buf->writestring("const "); |
675 #if DMDV2 | 680 #if DMDV2 |
676 if (d->isInvariant()) | 681 if (d->isInvariant()) |
677 buf->writestring("invariant "); | 682 buf->writestring("immutable "); |
678 #endif | 683 #endif |
679 if (d->isFinal()) | 684 if (d->isFinal()) |
680 buf->writestring("final "); | 685 buf->writestring("final "); |
681 if (d->isSynchronized()) | 686 if (d->isSynchronized()) |
682 buf->writestring("synchronized "); | 687 buf->writestring("synchronized "); |
946 | 951 |
947 void DocComment::parseSections(unsigned char *comment) | 952 void DocComment::parseSections(unsigned char *comment) |
948 { unsigned char *p; | 953 { unsigned char *p; |
949 unsigned char *pstart; | 954 unsigned char *pstart; |
950 unsigned char *pend; | 955 unsigned char *pend; |
951 unsigned char *q; | |
952 unsigned char *idstart; | 956 unsigned char *idstart; |
953 unsigned idlen; | 957 unsigned idlen; |
954 | 958 |
955 unsigned char *name = NULL; | 959 unsigned char *name = NULL; |
956 unsigned namelen = 0; | 960 unsigned namelen = 0; |
961 { | 965 { |
962 p = skipwhitespace(p); | 966 p = skipwhitespace(p); |
963 pstart = p; | 967 pstart = p; |
964 | 968 |
965 /* Find end of section, which is ended by one of: | 969 /* Find end of section, which is ended by one of: |
966 * 'identifier:' | 970 * 'identifier:' (but not inside a code section) |
967 * '\0' | 971 * '\0' |
968 */ | 972 */ |
969 idlen = 0; | 973 idlen = 0; |
974 int inCode = 0; | |
970 while (1) | 975 while (1) |
971 { | 976 { |
972 if (isalpha(*p) || *p == '_') | 977 // Check for start/end of a code section |
978 if (*p == '-') | |
973 { | 979 { |
974 q = p + 1; | 980 int numdash = 0; |
975 while (isalnum(*q) || *q == '_') | 981 while (*p == '-') |
976 q++; | 982 { |
983 ++numdash; | |
984 p++; | |
985 } | |
986 // BUG: handle UTF PS and LS too | |
987 if (!*p || *p == '\r' || *p == '\n' && numdash >= 3) | |
988 inCode ^= 1; | |
989 } | |
990 | |
991 if (!inCode && isIdStart(p)) | |
992 { | |
993 unsigned char *q = p + utfStride(p); | |
994 while (isIdTail(q)) | |
995 q += utfStride(q); | |
977 if (*q == ':') // identifier: ends it | 996 if (*q == ':') // identifier: ends it |
978 { idlen = q - p; | 997 { idlen = q - p; |
979 idstart = p; | 998 idstart = p; |
980 for (pend = p; pend > pstart; pend--) | 999 for (pend = p; pend > pstart; pend--) |
981 { if (pend[-1] == '\n') | 1000 { if (pend[-1] == '\n') |
1139 | 1158 |
1140 buf->writestring("$(DDOC_PARAMS \n"); | 1159 buf->writestring("$(DDOC_PARAMS \n"); |
1141 while (p < pend) | 1160 while (p < pend) |
1142 { | 1161 { |
1143 // Skip to start of macro | 1162 // Skip to start of macro |
1144 for (; 1; p++) | 1163 while (1) |
1145 { | 1164 { |
1146 switch (*p) | 1165 switch (*p) |
1147 { | 1166 { |
1148 case ' ': | 1167 case ' ': |
1149 case '\t': | 1168 case '\t': |
1169 p++; | |
1150 continue; | 1170 continue; |
1151 | 1171 |
1152 case '\n': | 1172 case '\n': |
1153 p++; | 1173 p++; |
1154 goto Lcont; | 1174 goto Lcont; |
1155 | 1175 |
1156 default: | 1176 default: |
1157 if (!(isalpha(*p) || *p == '_')) | 1177 if (isIdStart(p)) |
1158 { | 1178 break; |
1159 if (namelen) | 1179 if (namelen) |
1160 goto Ltext; // continuation of prev macro | 1180 goto Ltext; // continuation of prev macro |
1161 goto Lskipline; | 1181 goto Lskipline; |
1162 } | |
1163 break; | |
1164 } | 1182 } |
1165 break; | 1183 break; |
1166 } | 1184 } |
1167 tempstart = p; | 1185 tempstart = p; |
1168 | 1186 |
1169 while (isalnum(*p) || *p == '_') | 1187 while (isIdTail(p)) |
1170 p++; | 1188 p += utfStride(p); |
1171 templen = p - tempstart; | 1189 templen = p - tempstart; |
1172 | 1190 |
1173 while (*p == ' ' || *p == '\t') | 1191 while (*p == ' ' || *p == '\t') |
1174 p++; | 1192 p++; |
1175 | 1193 |
1267 unsigned textlen; | 1285 unsigned textlen; |
1268 | 1286 |
1269 while (p < pend) | 1287 while (p < pend) |
1270 { | 1288 { |
1271 // Skip to start of macro | 1289 // Skip to start of macro |
1272 for (; 1; p++) | 1290 while (1) |
1273 { | 1291 { |
1274 if (p >= pend) | 1292 if (p >= pend) |
1275 goto Ldone; | 1293 goto Ldone; |
1276 switch (*p) | 1294 switch (*p) |
1277 { | 1295 { |
1278 case ' ': | 1296 case ' ': |
1279 case '\t': | 1297 case '\t': |
1298 p++; | |
1280 continue; | 1299 continue; |
1281 | 1300 |
1282 case '\n': | 1301 case '\n': |
1283 p++; | 1302 p++; |
1284 goto Lcont; | 1303 goto Lcont; |
1285 | 1304 |
1286 default: | 1305 default: |
1287 if (!(isalpha(*p) || *p == '_')) | 1306 if (isIdStart(p)) |
1288 { | 1307 break; |
1289 if (namelen) | 1308 if (namelen) |
1290 goto Ltext; // continuation of prev macro | 1309 goto Ltext; // continuation of prev macro |
1291 goto Lskipline; | 1310 goto Lskipline; |
1292 } | |
1293 break; | |
1294 } | 1311 } |
1295 break; | 1312 break; |
1296 } | 1313 } |
1297 tempstart = p; | 1314 tempstart = p; |
1298 | 1315 |
1299 while (1) | 1316 while (1) |
1300 { | 1317 { |
1301 if (p >= pend) | 1318 if (p >= pend) |
1302 goto Ldone; | 1319 goto Ldone; |
1303 if (!(isalnum(*p) || *p == '_')) | 1320 if (!isIdTail(p)) |
1304 break; | 1321 break; |
1305 p++; | 1322 p += utfStride(p); |
1306 } | 1323 } |
1307 templen = p - tempstart; | 1324 templen = p - tempstart; |
1308 | 1325 |
1309 while (1) | 1326 while (1) |
1310 { | 1327 { |
1484 * start of identifier | 1501 * start of identifier |
1485 * beginning of next line | 1502 * beginning of next line |
1486 * end of buf | 1503 * end of buf |
1487 */ | 1504 */ |
1488 | 1505 |
1489 unsigned skiptoident(OutBuffer *buf, unsigned i) | 1506 unsigned skiptoident(OutBuffer *buf, size_t i) |
1490 { | 1507 { |
1491 for (; i < buf->offset; i++) | 1508 while (i < buf->offset) |
1492 { | 1509 { dchar_t c; |
1493 // BUG: handle unicode alpha's | 1510 |
1494 unsigned char c = buf->data[i]; | 1511 size_t oi = i; |
1495 if (isalpha(c) || c == '_') | 1512 if (utf_decodeChar((unsigned char *)buf->data, buf->offset, &i, &c)) |
1513 /* Ignore UTF errors, but still consume input | |
1514 */ | |
1496 break; | 1515 break; |
1497 if (c == '\n') | 1516 if (c >= 0x80) |
1498 break; | 1517 { |
1518 if (!isUniAlpha(c)) | |
1519 continue; | |
1520 } | |
1521 else if (!(isalpha(c) || c == '_' || c == '\n')) | |
1522 continue; | |
1523 i = oi; | |
1524 break; | |
1499 } | 1525 } |
1500 return i; | 1526 return i; |
1501 } | 1527 } |
1502 | 1528 |
1503 /************************************************ | 1529 /************************************************ |
1504 * Scan forward past end of identifier. | 1530 * Scan forward past end of identifier. |
1505 */ | 1531 */ |
1506 | 1532 |
1507 unsigned skippastident(OutBuffer *buf, unsigned i) | 1533 unsigned skippastident(OutBuffer *buf, size_t i) |
1508 { | 1534 { |
1509 for (; i < buf->offset; i++) | 1535 while (i < buf->offset) |
1510 { | 1536 { dchar_t c; |
1511 // BUG: handle unicode alpha's | 1537 |
1512 unsigned char c = buf->data[i]; | 1538 size_t oi = i; |
1513 if (!(isalnum(c) || c == '_')) | 1539 if (utf_decodeChar((unsigned char *)buf->data, buf->offset, &i, &c)) |
1540 /* Ignore UTF errors, but still consume input | |
1541 */ | |
1514 break; | 1542 break; |
1543 if (c >= 0x80) | |
1544 { | |
1545 if (isUniAlpha(c)) | |
1546 continue; | |
1547 } | |
1548 else if (isalnum(c) || c == '_') | |
1549 continue; | |
1550 i = oi; | |
1551 break; | |
1515 } | 1552 } |
1516 return i; | 1553 return i; |
1517 } | 1554 } |
1518 | 1555 |
1519 | 1556 |
1523 * Returns: | 1560 * Returns: |
1524 * i if not a URL | 1561 * i if not a URL |
1525 * index just past it if it is a URL | 1562 * index just past it if it is a URL |
1526 */ | 1563 */ |
1527 | 1564 |
1528 unsigned skippastURL(OutBuffer *buf, unsigned i) | 1565 unsigned skippastURL(OutBuffer *buf, size_t i) |
1529 { unsigned length = buf->offset - i; | 1566 { unsigned length = buf->offset - i; |
1530 unsigned char *p = &buf->data[i]; | 1567 unsigned char *p = &buf->data[i]; |
1531 unsigned j; | 1568 unsigned j; |
1532 unsigned sawdot = 0; | 1569 unsigned sawdot = 0; |
1533 | 1570 |
1808 } | 1845 } |
1809 break; | 1846 break; |
1810 | 1847 |
1811 default: | 1848 default: |
1812 leadingBlank = 0; | 1849 leadingBlank = 0; |
1813 if (sc && !inCode && (isalpha(c) || c == '_')) | 1850 if (sc && !inCode && isIdStart(&buf->data[i])) |
1814 { unsigned j; | 1851 { unsigned j; |
1815 | 1852 |
1816 j = skippastident(buf, i); | 1853 j = skippastident(buf, i); |
1817 if (j > i) | 1854 if (j > i) |
1818 { | 1855 { |
1879 size_t len = strlen(se); | 1916 size_t len = strlen(se); |
1880 buf->remove(i, 1); | 1917 buf->remove(i, 1); |
1881 i = buf->insert(i, se, len); | 1918 i = buf->insert(i, se, len); |
1882 i--; // point to ';' | 1919 i--; // point to ';' |
1883 } | 1920 } |
1884 else if (isalpha(c) || c == '_') | 1921 else if (isIdStart(&buf->data[i])) |
1885 { unsigned j; | 1922 { unsigned j; |
1886 | 1923 |
1887 j = skippastident(buf, i); | 1924 j = skippastident(buf, i); |
1888 if (j > i) | 1925 if (j > i) |
1889 { | 1926 { |
2015 break; | 2052 break; |
2016 } | 2053 } |
2017 return s; | 2054 return s; |
2018 } | 2055 } |
2019 | 2056 |
2057 /**************************************** | |
2058 * Determine if p points to the start of an identifier. | |
2059 */ | |
2060 | |
2061 int isIdStart(unsigned char *p) | |
2062 { | |
2063 unsigned c = *p; | |
2064 if (isalpha(c) || c == '_') | |
2065 return 1; | |
2066 if (c >= 0x80) | |
2067 { size_t i = 0; | |
2068 if (utf_decodeChar(p, 4, &i, &c)) | |
2069 return 0; // ignore errors | |
2070 if (isUniAlpha(c)) | |
2071 return 1; | |
2072 } | |
2073 return 0; | |
2074 } | |
2075 | |
2076 /**************************************** | |
2077 * Determine if p points to the rest of an identifier. | |
2078 */ | |
2079 | |
2080 int isIdTail(unsigned char *p) | |
2081 { | |
2082 unsigned c = *p; | |
2083 if (isalnum(c) || c == '_') | |
2084 return 1; | |
2085 if (c >= 0x80) | |
2086 { size_t i = 0; | |
2087 if (utf_decodeChar(p, 4, &i, &c)) | |
2088 return 0; // ignore errors | |
2089 if (isUniAlpha(c)) | |
2090 return 1; | |
2091 } | |
2092 return 0; | |
2093 } | |
2094 | |
2095 /***************************************** | |
2096 * Return number of bytes in UTF character. | |
2097 */ | |
2098 | |
2099 int utfStride(unsigned char *p) | |
2100 { | |
2101 unsigned c = *p; | |
2102 if (c < 0x80) | |
2103 return 1; | |
2104 size_t i = 0; | |
2105 utf_decodeChar(p, 4, &i, &c); // ignore errors, but still consume input | |
2106 return i; | |
2107 } |