Fossil SCM
Simplification of buffer management in the markdown formatter.
Commit
f8e9197de45da6790918e3e7bcca9c05c1f5f3707e8eb1c3aa3f2ab57daea2e0
Parent
7949d941c631896…
2 files changed
+40
-86
-1
+40
-86
| --- src/markdown.c | ||
| +++ src/markdown.c | ||
| @@ -85,11 +85,10 @@ | ||
| 85 | 85 | /* low level callbacks - NULL copies input directly into the output */ |
| 86 | 86 | void (*entity)(struct Blob *ob, struct Blob *entity, void *opaque); |
| 87 | 87 | void (*normal_text)(struct Blob *ob, struct Blob *text, void *opaque); |
| 88 | 88 | |
| 89 | 89 | /* renderer data */ |
| 90 | - int max_work_stack; /* prevent arbitrary deep recursion, cf README */ | |
| 91 | 90 | const char *emph_chars; /* chars that trigger emphasis rendering */ |
| 92 | 91 | void *opaque; /* opaque data send to every rendering callback */ |
| 93 | 92 | }; |
| 94 | 93 | |
| 95 | 94 | |
| @@ -154,12 +153,12 @@ | ||
| 154 | 153 | /* render -- structure containing one particular render */ |
| 155 | 154 | struct render { |
| 156 | 155 | struct mkd_renderer make; |
| 157 | 156 | struct Blob refs; |
| 158 | 157 | char_trigger active_char[256]; |
| 159 | - int work_active; | |
| 160 | - struct Blob *work; | |
| 158 | + int nBlobCache; /* Number of entries in aBlobCache */ | |
| 159 | + struct Blob *aBlobCache[20]; /* Cache of Blobs available for reuse */ | |
| 161 | 160 | }; |
| 162 | 161 | |
| 163 | 162 | |
| 164 | 163 | /* html_tag -- structure for quick HTML tag search (inspired from discount) */ |
| 165 | 164 | struct html_tag { |
| @@ -301,29 +300,32 @@ | ||
| 301 | 300 | sizeof block_tags[0], |
| 302 | 301 | cmp_html_tag); |
| 303 | 302 | } |
| 304 | 303 | |
| 305 | 304 | |
| 306 | -/* new_work_buffer -- get a new working buffer from the stack or create one */ | |
| 305 | +/* get a new working buffer from the cache or create one */ | |
| 307 | 306 | static struct Blob *new_work_buffer(struct render *rndr){ |
| 308 | - struct Blob *ret = 0; | |
| 309 | - | |
| 310 | - if( rndr->work_active < rndr->make.max_work_stack ){ | |
| 311 | - ret = rndr->work + rndr->work_active; | |
| 312 | - rndr->work_active += 1; | |
| 313 | - blob_reset(ret); | |
| 307 | + struct Blob *ret; | |
| 308 | + if( rndr->nBlobCache ){ | |
| 309 | + ret = rndr->aBlobCache[--rndr->nBlobCache]; | |
| 310 | + }else{ | |
| 311 | + ret = fossil_malloc(sizeof(*ret)); | |
| 314 | 312 | } |
| 313 | + *ret = empty_blob; | |
| 315 | 314 | return ret; |
| 316 | 315 | } |
| 317 | 316 | |
| 318 | 317 | |
| 319 | -/* release_work_buffer -- release the given working buffer */ | |
| 318 | +/* release the given working buffer back to the cache */ | |
| 320 | 319 | static void release_work_buffer(struct render *rndr, struct Blob *buf){ |
| 321 | 320 | if( !buf ) return; |
| 322 | - assert(rndr->work_active>0 && buf==(rndr->work+rndr->work_active-1)); | |
| 323 | - rndr->work_active -= 1; | |
| 324 | 321 | blob_reset(buf); |
| 322 | + if( rndr->nBlobCache < sizeof(rndr->aBlobCache)/sizeof(rndr->aBlobCache[0]) ){ | |
| 323 | + rndr->aBlobCache[rndr->nBlobCache++] = buf; | |
| 324 | + }else{ | |
| 325 | + fossil_free(buf); | |
| 326 | + } | |
| 325 | 327 | } |
| 326 | 328 | |
| 327 | 329 | |
| 328 | 330 | |
| 329 | 331 | /**************************** |
| @@ -1296,17 +1298,12 @@ | ||
| 1296 | 1298 | } |
| 1297 | 1299 | beg = end; |
| 1298 | 1300 | } |
| 1299 | 1301 | |
| 1300 | 1302 | if( rndr->make.blockquote ){ |
| 1301 | - struct Blob fallback = BLOB_INITIALIZER; | |
| 1302 | - if( out ){ | |
| 1303 | - parse_block(out, rndr, work_data, work_size); | |
| 1304 | - }else{ | |
| 1305 | - blob_init(&fallback, work_data, work_size); | |
| 1306 | - } | |
| 1307 | - rndr->make.blockquote(ob, out ? out : &fallback, rndr->make.opaque); | |
| 1303 | + parse_block(out, rndr, work_data, work_size); | |
| 1304 | + rndr->make.blockquote(ob, out, rndr->make.opaque); | |
| 1308 | 1305 | } |
| 1309 | 1306 | release_work_buffer(rndr, out); |
| 1310 | 1307 | return end; |
| 1311 | 1308 | } |
| 1312 | 1309 | |
| @@ -1320,11 +1317,10 @@ | ||
| 1320 | 1317 | ){ |
| 1321 | 1318 | size_t i = 0, end = 0; |
| 1322 | 1319 | int level = 0; |
| 1323 | 1320 | char *work_data = data; |
| 1324 | 1321 | size_t work_size = 0; |
| 1325 | - struct Blob fallback = BLOB_INITIALIZER; | |
| 1326 | 1322 | |
| 1327 | 1323 | while( i<size ){ |
| 1328 | 1324 | for(end=i+1; end<size && data[end-1]!='\n'; end++); |
| 1329 | 1325 | if( is_empty(data+i, size-i) |
| 1330 | 1326 | || (level = is_headerline(data+i, size-i))!= 0 |
| @@ -1342,16 +1338,12 @@ | ||
| 1342 | 1338 | while( work_size && data[work_size-1]=='\n' ){ work_size--; } |
| 1343 | 1339 | |
| 1344 | 1340 | if( !level ){ |
| 1345 | 1341 | if( rndr->make.paragraph ){ |
| 1346 | 1342 | struct Blob *tmp = new_work_buffer(rndr); |
| 1347 | - if( tmp ){ | |
| 1348 | - parse_inline(tmp, rndr, work_data, work_size); | |
| 1349 | - }else{ | |
| 1350 | - blob_init(&fallback, work_data, work_size); | |
| 1351 | - } | |
| 1352 | - rndr->make.paragraph(ob, tmp ? tmp : &fallback, rndr->make.opaque); | |
| 1343 | + parse_inline(tmp, rndr, work_data, work_size); | |
| 1344 | + rndr->make.paragraph(ob, tmp, rndr->make.opaque); | |
| 1353 | 1345 | release_work_buffer(rndr, tmp); |
| 1354 | 1346 | } |
| 1355 | 1347 | }else{ |
| 1356 | 1348 | if( work_size ){ |
| 1357 | 1349 | size_t beg; |
| @@ -1360,17 +1352,13 @@ | ||
| 1360 | 1352 | while( work_size && data[work_size]!='\n' ){ work_size--; } |
| 1361 | 1353 | beg = work_size+1; |
| 1362 | 1354 | while( work_size && data[work_size-1]=='\n'){ work_size--; } |
| 1363 | 1355 | if( work_size ){ |
| 1364 | 1356 | struct Blob *tmp = new_work_buffer(rndr); |
| 1365 | - if( tmp ){ | |
| 1366 | - parse_inline(tmp, rndr, work_data, work_size); | |
| 1367 | - }else{ | |
| 1368 | - blob_init (&fallback, work_data, work_size); | |
| 1369 | - } | |
| 1357 | + parse_inline(tmp, rndr, work_data, work_size); | |
| 1370 | 1358 | if( rndr->make.paragraph ){ |
| 1371 | - rndr->make.paragraph(ob, tmp ? tmp : &fallback, rndr->make.opaque); | |
| 1359 | + rndr->make.paragraph(ob, tmp, rndr->make.opaque); | |
| 1372 | 1360 | } |
| 1373 | 1361 | release_work_buffer(rndr, tmp); |
| 1374 | 1362 | work_data += beg; |
| 1375 | 1363 | work_size = i - beg; |
| 1376 | 1364 | }else{ |
| @@ -1378,17 +1366,12 @@ | ||
| 1378 | 1366 | } |
| 1379 | 1367 | } |
| 1380 | 1368 | |
| 1381 | 1369 | if( rndr->make.header ){ |
| 1382 | 1370 | struct Blob *span = new_work_buffer(rndr); |
| 1383 | - if( span ){ | |
| 1384 | - parse_inline(span, rndr, work_data, work_size); | |
| 1385 | - rndr->make.header(ob, span, level, rndr->make.opaque); | |
| 1386 | - }else{ | |
| 1387 | - blob_init(&fallback, work_data, work_size); | |
| 1388 | - rndr->make.header(ob, &fallback, level, rndr->make.opaque); | |
| 1389 | - } | |
| 1371 | + parse_inline(span, rndr, work_data, work_size); | |
| 1372 | + rndr->make.header(ob, span, level, rndr->make.opaque); | |
| 1390 | 1373 | release_work_buffer(rndr, span); |
| 1391 | 1374 | } |
| 1392 | 1375 | } |
| 1393 | 1376 | return end; |
| 1394 | 1377 | } |
| @@ -1448,11 +1431,10 @@ | ||
| 1448 | 1431 | struct render *rndr, |
| 1449 | 1432 | char *data, |
| 1450 | 1433 | size_t size, |
| 1451 | 1434 | int *flags |
| 1452 | 1435 | ){ |
| 1453 | - struct Blob fallback = BLOB_INITIALIZER; | |
| 1454 | 1436 | struct Blob *work = 0, *inter = 0; |
| 1455 | 1437 | size_t beg = 0, end, pre, sublist = 0, orgpre = 0, i; |
| 1456 | 1438 | int in_empty = 0, has_inside_empty = 0; |
| 1457 | 1439 | |
| 1458 | 1440 | /* keeping track of the first indentation prefix */ |
| @@ -1473,11 +1455,10 @@ | ||
| 1473 | 1455 | while( end<size && data[end-1]!='\n' ){ end++; } |
| 1474 | 1456 | |
| 1475 | 1457 | /* getting working buffers */ |
| 1476 | 1458 | work = new_work_buffer(rndr); |
| 1477 | 1459 | inter = new_work_buffer(rndr); |
| 1478 | - if( !work ) work = &fallback; | |
| 1479 | 1460 | |
| 1480 | 1461 | /* putting the first line into the working buffer */ |
| 1481 | 1462 | blob_append(work, data+beg, end-beg); |
| 1482 | 1463 | beg = end; |
| 1483 | 1464 | |
| @@ -1538,12 +1519,11 @@ | ||
| 1538 | 1519 | /* non-recursive fallback when working buffer stack is full */ |
| 1539 | 1520 | if( !inter ){ |
| 1540 | 1521 | if( rndr->make.listitem ){ |
| 1541 | 1522 | rndr->make.listitem(ob, work, *flags, rndr->make.opaque); |
| 1542 | 1523 | } |
| 1543 | - if( work!=&fallback ) release_work_buffer(rndr, work); | |
| 1544 | - blob_reset(&fallback); | |
| 1524 | + release_work_buffer(rndr, work); | |
| 1545 | 1525 | return beg; |
| 1546 | 1526 | } |
| 1547 | 1527 | |
| 1548 | 1528 | /* render of li contents */ |
| 1549 | 1529 | if( has_inside_empty ) *flags |= MKD_LI_BLOCK; |
| @@ -1574,12 +1554,11 @@ | ||
| 1574 | 1554 | /* render of li itself */ |
| 1575 | 1555 | if( rndr->make.listitem ){ |
| 1576 | 1556 | rndr->make.listitem(ob, inter, *flags, rndr->make.opaque); |
| 1577 | 1557 | } |
| 1578 | 1558 | release_work_buffer(rndr, inter); |
| 1579 | - if( work!=&fallback ) release_work_buffer(rndr, work); | |
| 1580 | - blob_reset(&fallback); | |
| 1559 | + release_work_buffer(rndr, work); | |
| 1581 | 1560 | return beg; |
| 1582 | 1561 | } |
| 1583 | 1562 | |
| 1584 | 1563 | |
| 1585 | 1564 | /* parse_list -- parsing ordered or unordered list block */ |
| @@ -1588,24 +1567,21 @@ | ||
| 1588 | 1567 | struct render *rndr, |
| 1589 | 1568 | char *data, |
| 1590 | 1569 | size_t size, |
| 1591 | 1570 | int flags |
| 1592 | 1571 | ){ |
| 1593 | - struct Blob fallback = BLOB_INITIALIZER; | |
| 1594 | 1572 | struct Blob *work = new_work_buffer(rndr); |
| 1595 | 1573 | size_t i = 0, j; |
| 1596 | - if( !work ) work = &fallback; | |
| 1597 | 1574 | |
| 1598 | 1575 | while( i<size ){ |
| 1599 | 1576 | j = parse_listitem(work, rndr, data+i, size-i, &flags); |
| 1600 | 1577 | i += j; |
| 1601 | 1578 | if( !j || (flags & MKD_LI_END) ) break; |
| 1602 | 1579 | } |
| 1603 | 1580 | |
| 1604 | 1581 | if( rndr->make.list ) rndr->make.list(ob, work, flags, rndr->make.opaque); |
| 1605 | - if( work!=&fallback ) release_work_buffer(rndr, work); | |
| 1606 | - blob_reset(&fallback); | |
| 1582 | + release_work_buffer(rndr, work); | |
| 1607 | 1583 | return i; |
| 1608 | 1584 | } |
| 1609 | 1585 | |
| 1610 | 1586 | |
| 1611 | 1587 | /* parse_atxheader -- parsing of atx-style headers */ |
| @@ -1631,19 +1607,13 @@ | ||
| 1631 | 1607 | while( end && (data[end-1]==' ' || data[end-1]=='\t') ){ end--; } |
| 1632 | 1608 | if( end<=i ) return parse_paragraph(ob, rndr, data, size); |
| 1633 | 1609 | |
| 1634 | 1610 | span_size = end-span_beg; |
| 1635 | 1611 | if( rndr->make.header ){ |
| 1636 | - struct Blob fallback = BLOB_INITIALIZER; | |
| 1637 | 1612 | struct Blob *span = new_work_buffer(rndr); |
| 1638 | - | |
| 1639 | - if( span ){ | |
| 1640 | - parse_inline(span, rndr, data+span_beg, span_size); | |
| 1641 | - }else{ | |
| 1642 | - blob_init(&fallback, data+span_beg, span_size); | |
| 1643 | - } | |
| 1644 | - rndr->make.header(ob, span ? span : &fallback, level, rndr->make.opaque); | |
| 1613 | + parse_inline(span, rndr, data+span_beg, span_size); | |
| 1614 | + rndr->make.header(ob, span, level, rndr->make.opaque); | |
| 1645 | 1615 | release_work_buffer(rndr, span); |
| 1646 | 1616 | } |
| 1647 | 1617 | return skip; |
| 1648 | 1618 | } |
| 1649 | 1619 | |
| @@ -1800,19 +1770,13 @@ | ||
| 1800 | 1770 | struct render *rndr, /* renderer description */ |
| 1801 | 1771 | char *data, /* input text */ |
| 1802 | 1772 | size_t size, /* input text size */ |
| 1803 | 1773 | int flags /* table flags */ |
| 1804 | 1774 | ){ |
| 1805 | - struct Blob fallback = BLOB_INITIALIZER; | |
| 1806 | 1775 | struct Blob *span = new_work_buffer(rndr); |
| 1807 | - | |
| 1808 | - if( span ){ | |
| 1809 | - parse_inline(span, rndr, data, size); | |
| 1810 | - }else{ | |
| 1811 | - blob_init(&fallback, data, size); | |
| 1812 | - } | |
| 1813 | - rndr->make.table_cell(ob, span ? span : &fallback, flags, rndr->make.opaque); | |
| 1776 | + parse_inline(span, rndr, data, size); | |
| 1777 | + rndr->make.table_cell(ob, span, flags, rndr->make.opaque); | |
| 1814 | 1778 | release_work_buffer(rndr, span); |
| 1815 | 1779 | } |
| 1816 | 1780 | |
| 1817 | 1781 | |
| 1818 | 1782 | /* parse_table_row -- parse an input line into a table row */ |
| @@ -1878,17 +1842,11 @@ | ||
| 1878 | 1842 | |
| 1879 | 1843 | col++; |
| 1880 | 1844 | } |
| 1881 | 1845 | |
| 1882 | 1846 | /* render the whole row and clean up */ |
| 1883 | - if( cells ){ | |
| 1884 | - rndr->make.table_row(ob, cells, flags, rndr->make.opaque); | |
| 1885 | - }else{ | |
| 1886 | - struct Blob fallback = BLOB_INITIALIZER; | |
| 1887 | - blob_init(&fallback, data, total ? total : size); | |
| 1888 | - rndr->make.table_row(ob, &fallback, flags, rndr->make.opaque); | |
| 1889 | - } | |
| 1847 | + rndr->make.table_row(ob, cells, flags, rndr->make.opaque); | |
| 1890 | 1848 | release_work_buffer(rndr, cells); |
| 1891 | 1849 | return total ? total : size; |
| 1892 | 1850 | } |
| 1893 | 1851 | |
| 1894 | 1852 | |
| @@ -1900,24 +1858,22 @@ | ||
| 1900 | 1858 | size_t size |
| 1901 | 1859 | ){ |
| 1902 | 1860 | size_t i = 0, head_end, col; |
| 1903 | 1861 | size_t align_size = 0; |
| 1904 | 1862 | int *aligns = 0; |
| 1905 | - struct Blob fallback = BLOB_INITIALIZER; | |
| 1906 | 1863 | struct Blob *head = 0; |
| 1907 | 1864 | struct Blob *rows = new_work_buffer(rndr); |
| 1908 | - if( !rows ) rows = &fallback; | |
| 1909 | 1865 | |
| 1910 | 1866 | /* skip the first (presumably header) line */ |
| 1911 | 1867 | while( i<size && data[i]!='\n' ){ i++; } |
| 1912 | 1868 | head_end = i; |
| 1913 | 1869 | |
| 1914 | 1870 | /* fallback on end of input */ |
| 1915 | 1871 | if( i>=size ){ |
| 1916 | 1872 | parse_table_row(rows, rndr, data, size, 0, 0, 0); |
| 1917 | 1873 | rndr->make.table(ob, 0, rows, rndr->make.opaque); |
| 1918 | - if( rows!=&fallback ) release_work_buffer(rndr, rows); | |
| 1874 | + release_work_buffer(rndr, rows); | |
| 1919 | 1875 | return i; |
| 1920 | 1876 | } |
| 1921 | 1877 | |
| 1922 | 1878 | /* attempt to parse a table rule, i.e. blanks, dash, colons and sep */ |
| 1923 | 1879 | i++; |
| @@ -1982,12 +1938,12 @@ | ||
| 1982 | 1938 | |
| 1983 | 1939 | /* render the full table */ |
| 1984 | 1940 | rndr->make.table(ob, head, rows, rndr->make.opaque); |
| 1985 | 1941 | |
| 1986 | 1942 | /* cleanup */ |
| 1987 | - if( head ) release_work_buffer(rndr, head); | |
| 1988 | - if( rows!=&fallback ) release_work_buffer(rndr, rows); | |
| 1943 | + release_work_buffer(rndr, head); | |
| 1944 | + release_work_buffer(rndr, rows); | |
| 1989 | 1945 | fossil_free(aligns); |
| 1990 | 1946 | return i; |
| 1991 | 1947 | } |
| 1992 | 1948 | |
| 1993 | 1949 | |
| @@ -2181,23 +2137,20 @@ | ||
| 2181 | 2137 | struct Blob *ob, /* output blob for rendered text */ |
| 2182 | 2138 | struct Blob *ib, /* input blob in markdown */ |
| 2183 | 2139 | const struct mkd_renderer *rndrer /* renderer descriptor (callbacks) */ |
| 2184 | 2140 | ){ |
| 2185 | 2141 | struct link_ref *lr; |
| 2186 | - struct Blob text = BLOB_INITIALIZER; | |
| 2187 | 2142 | size_t i, beg, end = 0; |
| 2188 | 2143 | struct render rndr; |
| 2189 | 2144 | char *ib_data; |
| 2145 | + Blob text = BLOB_INITIALIZER; | |
| 2190 | 2146 | |
| 2191 | 2147 | /* filling the render structure */ |
| 2192 | 2148 | if( !rndrer ) return; |
| 2193 | 2149 | rndr.make = *rndrer; |
| 2194 | - if( rndr.make.max_work_stack<1 ) rndr.make.max_work_stack = 1; | |
| 2195 | - rndr.work_active = 0; | |
| 2196 | - rndr.work = fossil_malloc(rndr.make.max_work_stack * sizeof *rndr.work); | |
| 2197 | - for(i=0; i<rndr.make.max_work_stack; i++) rndr.work[i] = text; | |
| 2198 | - rndr.refs = text; | |
| 2150 | + rndr.nBlobCache = 0; | |
| 2151 | + rndr.refs = empty_blob; | |
| 2199 | 2152 | for(i=0; i<256; i++) rndr.active_char[i] = 0; |
| 2200 | 2153 | if( (rndr.make.emphasis |
| 2201 | 2154 | || rndr.make.double_emphasis |
| 2202 | 2155 | || rndr.make.triple_emphasis) |
| 2203 | 2156 | && rndr.make.emph_chars |
| @@ -2260,8 +2213,9 @@ | ||
| 2260 | 2213 | blob_reset(&lr[i].id); |
| 2261 | 2214 | blob_reset(&lr[i].link); |
| 2262 | 2215 | blob_reset(&lr[i].title); |
| 2263 | 2216 | } |
| 2264 | 2217 | blob_reset(&rndr.refs); |
| 2265 | - blobarray_zero(rndr.work, rndr.make.max_work_stack); | |
| 2266 | - fossil_free(rndr.work); | |
| 2218 | + for(i=0; i<rndr.nBlobCache; i++){ | |
| 2219 | + fossil_free(rndr.aBlobCache[i]); | |
| 2220 | + } | |
| 2267 | 2221 | } |
| 2268 | 2222 |
| --- src/markdown.c | |
| +++ src/markdown.c | |
| @@ -85,11 +85,10 @@ | |
| 85 | /* low level callbacks - NULL copies input directly into the output */ |
| 86 | void (*entity)(struct Blob *ob, struct Blob *entity, void *opaque); |
| 87 | void (*normal_text)(struct Blob *ob, struct Blob *text, void *opaque); |
| 88 | |
| 89 | /* renderer data */ |
| 90 | int max_work_stack; /* prevent arbitrary deep recursion, cf README */ |
| 91 | const char *emph_chars; /* chars that trigger emphasis rendering */ |
| 92 | void *opaque; /* opaque data send to every rendering callback */ |
| 93 | }; |
| 94 | |
| 95 | |
| @@ -154,12 +153,12 @@ | |
| 154 | /* render -- structure containing one particular render */ |
| 155 | struct render { |
| 156 | struct mkd_renderer make; |
| 157 | struct Blob refs; |
| 158 | char_trigger active_char[256]; |
| 159 | int work_active; |
| 160 | struct Blob *work; |
| 161 | }; |
| 162 | |
| 163 | |
| 164 | /* html_tag -- structure for quick HTML tag search (inspired from discount) */ |
| 165 | struct html_tag { |
| @@ -301,29 +300,32 @@ | |
| 301 | sizeof block_tags[0], |
| 302 | cmp_html_tag); |
| 303 | } |
| 304 | |
| 305 | |
| 306 | /* new_work_buffer -- get a new working buffer from the stack or create one */ |
| 307 | static struct Blob *new_work_buffer(struct render *rndr){ |
| 308 | struct Blob *ret = 0; |
| 309 | |
| 310 | if( rndr->work_active < rndr->make.max_work_stack ){ |
| 311 | ret = rndr->work + rndr->work_active; |
| 312 | rndr->work_active += 1; |
| 313 | blob_reset(ret); |
| 314 | } |
| 315 | return ret; |
| 316 | } |
| 317 | |
| 318 | |
| 319 | /* release_work_buffer -- release the given working buffer */ |
| 320 | static void release_work_buffer(struct render *rndr, struct Blob *buf){ |
| 321 | if( !buf ) return; |
| 322 | assert(rndr->work_active>0 && buf==(rndr->work+rndr->work_active-1)); |
| 323 | rndr->work_active -= 1; |
| 324 | blob_reset(buf); |
| 325 | } |
| 326 | |
| 327 | |
| 328 | |
| 329 | /**************************** |
| @@ -1296,17 +1298,12 @@ | |
| 1296 | } |
| 1297 | beg = end; |
| 1298 | } |
| 1299 | |
| 1300 | if( rndr->make.blockquote ){ |
| 1301 | struct Blob fallback = BLOB_INITIALIZER; |
| 1302 | if( out ){ |
| 1303 | parse_block(out, rndr, work_data, work_size); |
| 1304 | }else{ |
| 1305 | blob_init(&fallback, work_data, work_size); |
| 1306 | } |
| 1307 | rndr->make.blockquote(ob, out ? out : &fallback, rndr->make.opaque); |
| 1308 | } |
| 1309 | release_work_buffer(rndr, out); |
| 1310 | return end; |
| 1311 | } |
| 1312 | |
| @@ -1320,11 +1317,10 @@ | |
| 1320 | ){ |
| 1321 | size_t i = 0, end = 0; |
| 1322 | int level = 0; |
| 1323 | char *work_data = data; |
| 1324 | size_t work_size = 0; |
| 1325 | struct Blob fallback = BLOB_INITIALIZER; |
| 1326 | |
| 1327 | while( i<size ){ |
| 1328 | for(end=i+1; end<size && data[end-1]!='\n'; end++); |
| 1329 | if( is_empty(data+i, size-i) |
| 1330 | || (level = is_headerline(data+i, size-i))!= 0 |
| @@ -1342,16 +1338,12 @@ | |
| 1342 | while( work_size && data[work_size-1]=='\n' ){ work_size--; } |
| 1343 | |
| 1344 | if( !level ){ |
| 1345 | if( rndr->make.paragraph ){ |
| 1346 | struct Blob *tmp = new_work_buffer(rndr); |
| 1347 | if( tmp ){ |
| 1348 | parse_inline(tmp, rndr, work_data, work_size); |
| 1349 | }else{ |
| 1350 | blob_init(&fallback, work_data, work_size); |
| 1351 | } |
| 1352 | rndr->make.paragraph(ob, tmp ? tmp : &fallback, rndr->make.opaque); |
| 1353 | release_work_buffer(rndr, tmp); |
| 1354 | } |
| 1355 | }else{ |
| 1356 | if( work_size ){ |
| 1357 | size_t beg; |
| @@ -1360,17 +1352,13 @@ | |
| 1360 | while( work_size && data[work_size]!='\n' ){ work_size--; } |
| 1361 | beg = work_size+1; |
| 1362 | while( work_size && data[work_size-1]=='\n'){ work_size--; } |
| 1363 | if( work_size ){ |
| 1364 | struct Blob *tmp = new_work_buffer(rndr); |
| 1365 | if( tmp ){ |
| 1366 | parse_inline(tmp, rndr, work_data, work_size); |
| 1367 | }else{ |
| 1368 | blob_init (&fallback, work_data, work_size); |
| 1369 | } |
| 1370 | if( rndr->make.paragraph ){ |
| 1371 | rndr->make.paragraph(ob, tmp ? tmp : &fallback, rndr->make.opaque); |
| 1372 | } |
| 1373 | release_work_buffer(rndr, tmp); |
| 1374 | work_data += beg; |
| 1375 | work_size = i - beg; |
| 1376 | }else{ |
| @@ -1378,17 +1366,12 @@ | |
| 1378 | } |
| 1379 | } |
| 1380 | |
| 1381 | if( rndr->make.header ){ |
| 1382 | struct Blob *span = new_work_buffer(rndr); |
| 1383 | if( span ){ |
| 1384 | parse_inline(span, rndr, work_data, work_size); |
| 1385 | rndr->make.header(ob, span, level, rndr->make.opaque); |
| 1386 | }else{ |
| 1387 | blob_init(&fallback, work_data, work_size); |
| 1388 | rndr->make.header(ob, &fallback, level, rndr->make.opaque); |
| 1389 | } |
| 1390 | release_work_buffer(rndr, span); |
| 1391 | } |
| 1392 | } |
| 1393 | return end; |
| 1394 | } |
| @@ -1448,11 +1431,10 @@ | |
| 1448 | struct render *rndr, |
| 1449 | char *data, |
| 1450 | size_t size, |
| 1451 | int *flags |
| 1452 | ){ |
| 1453 | struct Blob fallback = BLOB_INITIALIZER; |
| 1454 | struct Blob *work = 0, *inter = 0; |
| 1455 | size_t beg = 0, end, pre, sublist = 0, orgpre = 0, i; |
| 1456 | int in_empty = 0, has_inside_empty = 0; |
| 1457 | |
| 1458 | /* keeping track of the first indentation prefix */ |
| @@ -1473,11 +1455,10 @@ | |
| 1473 | while( end<size && data[end-1]!='\n' ){ end++; } |
| 1474 | |
| 1475 | /* getting working buffers */ |
| 1476 | work = new_work_buffer(rndr); |
| 1477 | inter = new_work_buffer(rndr); |
| 1478 | if( !work ) work = &fallback; |
| 1479 | |
| 1480 | /* putting the first line into the working buffer */ |
| 1481 | blob_append(work, data+beg, end-beg); |
| 1482 | beg = end; |
| 1483 | |
| @@ -1538,12 +1519,11 @@ | |
| 1538 | /* non-recursive fallback when working buffer stack is full */ |
| 1539 | if( !inter ){ |
| 1540 | if( rndr->make.listitem ){ |
| 1541 | rndr->make.listitem(ob, work, *flags, rndr->make.opaque); |
| 1542 | } |
| 1543 | if( work!=&fallback ) release_work_buffer(rndr, work); |
| 1544 | blob_reset(&fallback); |
| 1545 | return beg; |
| 1546 | } |
| 1547 | |
| 1548 | /* render of li contents */ |
| 1549 | if( has_inside_empty ) *flags |= MKD_LI_BLOCK; |
| @@ -1574,12 +1554,11 @@ | |
| 1574 | /* render of li itself */ |
| 1575 | if( rndr->make.listitem ){ |
| 1576 | rndr->make.listitem(ob, inter, *flags, rndr->make.opaque); |
| 1577 | } |
| 1578 | release_work_buffer(rndr, inter); |
| 1579 | if( work!=&fallback ) release_work_buffer(rndr, work); |
| 1580 | blob_reset(&fallback); |
| 1581 | return beg; |
| 1582 | } |
| 1583 | |
| 1584 | |
| 1585 | /* parse_list -- parsing ordered or unordered list block */ |
| @@ -1588,24 +1567,21 @@ | |
| 1588 | struct render *rndr, |
| 1589 | char *data, |
| 1590 | size_t size, |
| 1591 | int flags |
| 1592 | ){ |
| 1593 | struct Blob fallback = BLOB_INITIALIZER; |
| 1594 | struct Blob *work = new_work_buffer(rndr); |
| 1595 | size_t i = 0, j; |
| 1596 | if( !work ) work = &fallback; |
| 1597 | |
| 1598 | while( i<size ){ |
| 1599 | j = parse_listitem(work, rndr, data+i, size-i, &flags); |
| 1600 | i += j; |
| 1601 | if( !j || (flags & MKD_LI_END) ) break; |
| 1602 | } |
| 1603 | |
| 1604 | if( rndr->make.list ) rndr->make.list(ob, work, flags, rndr->make.opaque); |
| 1605 | if( work!=&fallback ) release_work_buffer(rndr, work); |
| 1606 | blob_reset(&fallback); |
| 1607 | return i; |
| 1608 | } |
| 1609 | |
| 1610 | |
| 1611 | /* parse_atxheader -- parsing of atx-style headers */ |
| @@ -1631,19 +1607,13 @@ | |
| 1631 | while( end && (data[end-1]==' ' || data[end-1]=='\t') ){ end--; } |
| 1632 | if( end<=i ) return parse_paragraph(ob, rndr, data, size); |
| 1633 | |
| 1634 | span_size = end-span_beg; |
| 1635 | if( rndr->make.header ){ |
| 1636 | struct Blob fallback = BLOB_INITIALIZER; |
| 1637 | struct Blob *span = new_work_buffer(rndr); |
| 1638 | |
| 1639 | if( span ){ |
| 1640 | parse_inline(span, rndr, data+span_beg, span_size); |
| 1641 | }else{ |
| 1642 | blob_init(&fallback, data+span_beg, span_size); |
| 1643 | } |
| 1644 | rndr->make.header(ob, span ? span : &fallback, level, rndr->make.opaque); |
| 1645 | release_work_buffer(rndr, span); |
| 1646 | } |
| 1647 | return skip; |
| 1648 | } |
| 1649 | |
| @@ -1800,19 +1770,13 @@ | |
| 1800 | struct render *rndr, /* renderer description */ |
| 1801 | char *data, /* input text */ |
| 1802 | size_t size, /* input text size */ |
| 1803 | int flags /* table flags */ |
| 1804 | ){ |
| 1805 | struct Blob fallback = BLOB_INITIALIZER; |
| 1806 | struct Blob *span = new_work_buffer(rndr); |
| 1807 | |
| 1808 | if( span ){ |
| 1809 | parse_inline(span, rndr, data, size); |
| 1810 | }else{ |
| 1811 | blob_init(&fallback, data, size); |
| 1812 | } |
| 1813 | rndr->make.table_cell(ob, span ? span : &fallback, flags, rndr->make.opaque); |
| 1814 | release_work_buffer(rndr, span); |
| 1815 | } |
| 1816 | |
| 1817 | |
| 1818 | /* parse_table_row -- parse an input line into a table row */ |
| @@ -1878,17 +1842,11 @@ | |
| 1878 | |
| 1879 | col++; |
| 1880 | } |
| 1881 | |
| 1882 | /* render the whole row and clean up */ |
| 1883 | if( cells ){ |
| 1884 | rndr->make.table_row(ob, cells, flags, rndr->make.opaque); |
| 1885 | }else{ |
| 1886 | struct Blob fallback = BLOB_INITIALIZER; |
| 1887 | blob_init(&fallback, data, total ? total : size); |
| 1888 | rndr->make.table_row(ob, &fallback, flags, rndr->make.opaque); |
| 1889 | } |
| 1890 | release_work_buffer(rndr, cells); |
| 1891 | return total ? total : size; |
| 1892 | } |
| 1893 | |
| 1894 | |
| @@ -1900,24 +1858,22 @@ | |
| 1900 | size_t size |
| 1901 | ){ |
| 1902 | size_t i = 0, head_end, col; |
| 1903 | size_t align_size = 0; |
| 1904 | int *aligns = 0; |
| 1905 | struct Blob fallback = BLOB_INITIALIZER; |
| 1906 | struct Blob *head = 0; |
| 1907 | struct Blob *rows = new_work_buffer(rndr); |
| 1908 | if( !rows ) rows = &fallback; |
| 1909 | |
| 1910 | /* skip the first (presumably header) line */ |
| 1911 | while( i<size && data[i]!='\n' ){ i++; } |
| 1912 | head_end = i; |
| 1913 | |
| 1914 | /* fallback on end of input */ |
| 1915 | if( i>=size ){ |
| 1916 | parse_table_row(rows, rndr, data, size, 0, 0, 0); |
| 1917 | rndr->make.table(ob, 0, rows, rndr->make.opaque); |
| 1918 | if( rows!=&fallback ) release_work_buffer(rndr, rows); |
| 1919 | return i; |
| 1920 | } |
| 1921 | |
| 1922 | /* attempt to parse a table rule, i.e. blanks, dash, colons and sep */ |
| 1923 | i++; |
| @@ -1982,12 +1938,12 @@ | |
| 1982 | |
| 1983 | /* render the full table */ |
| 1984 | rndr->make.table(ob, head, rows, rndr->make.opaque); |
| 1985 | |
| 1986 | /* cleanup */ |
| 1987 | if( head ) release_work_buffer(rndr, head); |
| 1988 | if( rows!=&fallback ) release_work_buffer(rndr, rows); |
| 1989 | fossil_free(aligns); |
| 1990 | return i; |
| 1991 | } |
| 1992 | |
| 1993 | |
| @@ -2181,23 +2137,20 @@ | |
| 2181 | struct Blob *ob, /* output blob for rendered text */ |
| 2182 | struct Blob *ib, /* input blob in markdown */ |
| 2183 | const struct mkd_renderer *rndrer /* renderer descriptor (callbacks) */ |
| 2184 | ){ |
| 2185 | struct link_ref *lr; |
| 2186 | struct Blob text = BLOB_INITIALIZER; |
| 2187 | size_t i, beg, end = 0; |
| 2188 | struct render rndr; |
| 2189 | char *ib_data; |
| 2190 | |
| 2191 | /* filling the render structure */ |
| 2192 | if( !rndrer ) return; |
| 2193 | rndr.make = *rndrer; |
| 2194 | if( rndr.make.max_work_stack<1 ) rndr.make.max_work_stack = 1; |
| 2195 | rndr.work_active = 0; |
| 2196 | rndr.work = fossil_malloc(rndr.make.max_work_stack * sizeof *rndr.work); |
| 2197 | for(i=0; i<rndr.make.max_work_stack; i++) rndr.work[i] = text; |
| 2198 | rndr.refs = text; |
| 2199 | for(i=0; i<256; i++) rndr.active_char[i] = 0; |
| 2200 | if( (rndr.make.emphasis |
| 2201 | || rndr.make.double_emphasis |
| 2202 | || rndr.make.triple_emphasis) |
| 2203 | && rndr.make.emph_chars |
| @@ -2260,8 +2213,9 @@ | |
| 2260 | blob_reset(&lr[i].id); |
| 2261 | blob_reset(&lr[i].link); |
| 2262 | blob_reset(&lr[i].title); |
| 2263 | } |
| 2264 | blob_reset(&rndr.refs); |
| 2265 | blobarray_zero(rndr.work, rndr.make.max_work_stack); |
| 2266 | fossil_free(rndr.work); |
| 2267 | } |
| 2268 |
| --- src/markdown.c | |
| +++ src/markdown.c | |
| @@ -85,11 +85,10 @@ | |
| 85 | /* low level callbacks - NULL copies input directly into the output */ |
| 86 | void (*entity)(struct Blob *ob, struct Blob *entity, void *opaque); |
| 87 | void (*normal_text)(struct Blob *ob, struct Blob *text, void *opaque); |
| 88 | |
| 89 | /* renderer data */ |
| 90 | const char *emph_chars; /* chars that trigger emphasis rendering */ |
| 91 | void *opaque; /* opaque data send to every rendering callback */ |
| 92 | }; |
| 93 | |
| 94 | |
| @@ -154,12 +153,12 @@ | |
| 153 | /* render -- structure containing one particular render */ |
| 154 | struct render { |
| 155 | struct mkd_renderer make; |
| 156 | struct Blob refs; |
| 157 | char_trigger active_char[256]; |
| 158 | int nBlobCache; /* Number of entries in aBlobCache */ |
| 159 | struct Blob *aBlobCache[20]; /* Cache of Blobs available for reuse */ |
| 160 | }; |
| 161 | |
| 162 | |
| 163 | /* html_tag -- structure for quick HTML tag search (inspired from discount) */ |
| 164 | struct html_tag { |
| @@ -301,29 +300,32 @@ | |
| 300 | sizeof block_tags[0], |
| 301 | cmp_html_tag); |
| 302 | } |
| 303 | |
| 304 | |
| 305 | /* get a new working buffer from the cache or create one */ |
| 306 | static struct Blob *new_work_buffer(struct render *rndr){ |
| 307 | struct Blob *ret; |
| 308 | if( rndr->nBlobCache ){ |
| 309 | ret = rndr->aBlobCache[--rndr->nBlobCache]; |
| 310 | }else{ |
| 311 | ret = fossil_malloc(sizeof(*ret)); |
| 312 | } |
| 313 | *ret = empty_blob; |
| 314 | return ret; |
| 315 | } |
| 316 | |
| 317 | |
| 318 | /* release the given working buffer back to the cache */ |
| 319 | static void release_work_buffer(struct render *rndr, struct Blob *buf){ |
| 320 | if( !buf ) return; |
| 321 | blob_reset(buf); |
| 322 | if( rndr->nBlobCache < sizeof(rndr->aBlobCache)/sizeof(rndr->aBlobCache[0]) ){ |
| 323 | rndr->aBlobCache[rndr->nBlobCache++] = buf; |
| 324 | }else{ |
| 325 | fossil_free(buf); |
| 326 | } |
| 327 | } |
| 328 | |
| 329 | |
| 330 | |
| 331 | /**************************** |
| @@ -1296,17 +1298,12 @@ | |
| 1298 | } |
| 1299 | beg = end; |
| 1300 | } |
| 1301 | |
| 1302 | if( rndr->make.blockquote ){ |
| 1303 | parse_block(out, rndr, work_data, work_size); |
| 1304 | rndr->make.blockquote(ob, out, rndr->make.opaque); |
| 1305 | } |
| 1306 | release_work_buffer(rndr, out); |
| 1307 | return end; |
| 1308 | } |
| 1309 | |
| @@ -1320,11 +1317,10 @@ | |
| 1317 | ){ |
| 1318 | size_t i = 0, end = 0; |
| 1319 | int level = 0; |
| 1320 | char *work_data = data; |
| 1321 | size_t work_size = 0; |
| 1322 | |
| 1323 | while( i<size ){ |
| 1324 | for(end=i+1; end<size && data[end-1]!='\n'; end++); |
| 1325 | if( is_empty(data+i, size-i) |
| 1326 | || (level = is_headerline(data+i, size-i))!= 0 |
| @@ -1342,16 +1338,12 @@ | |
| 1338 | while( work_size && data[work_size-1]=='\n' ){ work_size--; } |
| 1339 | |
| 1340 | if( !level ){ |
| 1341 | if( rndr->make.paragraph ){ |
| 1342 | struct Blob *tmp = new_work_buffer(rndr); |
| 1343 | parse_inline(tmp, rndr, work_data, work_size); |
| 1344 | rndr->make.paragraph(ob, tmp, rndr->make.opaque); |
| 1345 | release_work_buffer(rndr, tmp); |
| 1346 | } |
| 1347 | }else{ |
| 1348 | if( work_size ){ |
| 1349 | size_t beg; |
| @@ -1360,17 +1352,13 @@ | |
| 1352 | while( work_size && data[work_size]!='\n' ){ work_size--; } |
| 1353 | beg = work_size+1; |
| 1354 | while( work_size && data[work_size-1]=='\n'){ work_size--; } |
| 1355 | if( work_size ){ |
| 1356 | struct Blob *tmp = new_work_buffer(rndr); |
| 1357 | parse_inline(tmp, rndr, work_data, work_size); |
| 1358 | if( rndr->make.paragraph ){ |
| 1359 | rndr->make.paragraph(ob, tmp, rndr->make.opaque); |
| 1360 | } |
| 1361 | release_work_buffer(rndr, tmp); |
| 1362 | work_data += beg; |
| 1363 | work_size = i - beg; |
| 1364 | }else{ |
| @@ -1378,17 +1366,12 @@ | |
| 1366 | } |
| 1367 | } |
| 1368 | |
| 1369 | if( rndr->make.header ){ |
| 1370 | struct Blob *span = new_work_buffer(rndr); |
| 1371 | parse_inline(span, rndr, work_data, work_size); |
| 1372 | rndr->make.header(ob, span, level, rndr->make.opaque); |
| 1373 | release_work_buffer(rndr, span); |
| 1374 | } |
| 1375 | } |
| 1376 | return end; |
| 1377 | } |
| @@ -1448,11 +1431,10 @@ | |
| 1431 | struct render *rndr, |
| 1432 | char *data, |
| 1433 | size_t size, |
| 1434 | int *flags |
| 1435 | ){ |
| 1436 | struct Blob *work = 0, *inter = 0; |
| 1437 | size_t beg = 0, end, pre, sublist = 0, orgpre = 0, i; |
| 1438 | int in_empty = 0, has_inside_empty = 0; |
| 1439 | |
| 1440 | /* keeping track of the first indentation prefix */ |
| @@ -1473,11 +1455,10 @@ | |
| 1455 | while( end<size && data[end-1]!='\n' ){ end++; } |
| 1456 | |
| 1457 | /* getting working buffers */ |
| 1458 | work = new_work_buffer(rndr); |
| 1459 | inter = new_work_buffer(rndr); |
| 1460 | |
| 1461 | /* putting the first line into the working buffer */ |
| 1462 | blob_append(work, data+beg, end-beg); |
| 1463 | beg = end; |
| 1464 | |
| @@ -1538,12 +1519,11 @@ | |
| 1519 | /* non-recursive fallback when working buffer stack is full */ |
| 1520 | if( !inter ){ |
| 1521 | if( rndr->make.listitem ){ |
| 1522 | rndr->make.listitem(ob, work, *flags, rndr->make.opaque); |
| 1523 | } |
| 1524 | release_work_buffer(rndr, work); |
| 1525 | return beg; |
| 1526 | } |
| 1527 | |
| 1528 | /* render of li contents */ |
| 1529 | if( has_inside_empty ) *flags |= MKD_LI_BLOCK; |
| @@ -1574,12 +1554,11 @@ | |
| 1554 | /* render of li itself */ |
| 1555 | if( rndr->make.listitem ){ |
| 1556 | rndr->make.listitem(ob, inter, *flags, rndr->make.opaque); |
| 1557 | } |
| 1558 | release_work_buffer(rndr, inter); |
| 1559 | release_work_buffer(rndr, work); |
| 1560 | return beg; |
| 1561 | } |
| 1562 | |
| 1563 | |
| 1564 | /* parse_list -- parsing ordered or unordered list block */ |
| @@ -1588,24 +1567,21 @@ | |
| 1567 | struct render *rndr, |
| 1568 | char *data, |
| 1569 | size_t size, |
| 1570 | int flags |
| 1571 | ){ |
| 1572 | struct Blob *work = new_work_buffer(rndr); |
| 1573 | size_t i = 0, j; |
| 1574 | |
| 1575 | while( i<size ){ |
| 1576 | j = parse_listitem(work, rndr, data+i, size-i, &flags); |
| 1577 | i += j; |
| 1578 | if( !j || (flags & MKD_LI_END) ) break; |
| 1579 | } |
| 1580 | |
| 1581 | if( rndr->make.list ) rndr->make.list(ob, work, flags, rndr->make.opaque); |
| 1582 | release_work_buffer(rndr, work); |
| 1583 | return i; |
| 1584 | } |
| 1585 | |
| 1586 | |
| 1587 | /* parse_atxheader -- parsing of atx-style headers */ |
| @@ -1631,19 +1607,13 @@ | |
| 1607 | while( end && (data[end-1]==' ' || data[end-1]=='\t') ){ end--; } |
| 1608 | if( end<=i ) return parse_paragraph(ob, rndr, data, size); |
| 1609 | |
| 1610 | span_size = end-span_beg; |
| 1611 | if( rndr->make.header ){ |
| 1612 | struct Blob *span = new_work_buffer(rndr); |
| 1613 | parse_inline(span, rndr, data+span_beg, span_size); |
| 1614 | rndr->make.header(ob, span, level, rndr->make.opaque); |
| 1615 | release_work_buffer(rndr, span); |
| 1616 | } |
| 1617 | return skip; |
| 1618 | } |
| 1619 | |
| @@ -1800,19 +1770,13 @@ | |
| 1770 | struct render *rndr, /* renderer description */ |
| 1771 | char *data, /* input text */ |
| 1772 | size_t size, /* input text size */ |
| 1773 | int flags /* table flags */ |
| 1774 | ){ |
| 1775 | struct Blob *span = new_work_buffer(rndr); |
| 1776 | parse_inline(span, rndr, data, size); |
| 1777 | rndr->make.table_cell(ob, span, flags, rndr->make.opaque); |
| 1778 | release_work_buffer(rndr, span); |
| 1779 | } |
| 1780 | |
| 1781 | |
| 1782 | /* parse_table_row -- parse an input line into a table row */ |
| @@ -1878,17 +1842,11 @@ | |
| 1842 | |
| 1843 | col++; |
| 1844 | } |
| 1845 | |
| 1846 | /* render the whole row and clean up */ |
| 1847 | rndr->make.table_row(ob, cells, flags, rndr->make.opaque); |
| 1848 | release_work_buffer(rndr, cells); |
| 1849 | return total ? total : size; |
| 1850 | } |
| 1851 | |
| 1852 | |
| @@ -1900,24 +1858,22 @@ | |
| 1858 | size_t size |
| 1859 | ){ |
| 1860 | size_t i = 0, head_end, col; |
| 1861 | size_t align_size = 0; |
| 1862 | int *aligns = 0; |
| 1863 | struct Blob *head = 0; |
| 1864 | struct Blob *rows = new_work_buffer(rndr); |
| 1865 | |
| 1866 | /* skip the first (presumably header) line */ |
| 1867 | while( i<size && data[i]!='\n' ){ i++; } |
| 1868 | head_end = i; |
| 1869 | |
| 1870 | /* fallback on end of input */ |
| 1871 | if( i>=size ){ |
| 1872 | parse_table_row(rows, rndr, data, size, 0, 0, 0); |
| 1873 | rndr->make.table(ob, 0, rows, rndr->make.opaque); |
| 1874 | release_work_buffer(rndr, rows); |
| 1875 | return i; |
| 1876 | } |
| 1877 | |
| 1878 | /* attempt to parse a table rule, i.e. blanks, dash, colons and sep */ |
| 1879 | i++; |
| @@ -1982,12 +1938,12 @@ | |
| 1938 | |
| 1939 | /* render the full table */ |
| 1940 | rndr->make.table(ob, head, rows, rndr->make.opaque); |
| 1941 | |
| 1942 | /* cleanup */ |
| 1943 | release_work_buffer(rndr, head); |
| 1944 | release_work_buffer(rndr, rows); |
| 1945 | fossil_free(aligns); |
| 1946 | return i; |
| 1947 | } |
| 1948 | |
| 1949 | |
| @@ -2181,23 +2137,20 @@ | |
| 2137 | struct Blob *ob, /* output blob for rendered text */ |
| 2138 | struct Blob *ib, /* input blob in markdown */ |
| 2139 | const struct mkd_renderer *rndrer /* renderer descriptor (callbacks) */ |
| 2140 | ){ |
| 2141 | struct link_ref *lr; |
| 2142 | size_t i, beg, end = 0; |
| 2143 | struct render rndr; |
| 2144 | char *ib_data; |
| 2145 | Blob text = BLOB_INITIALIZER; |
| 2146 | |
| 2147 | /* filling the render structure */ |
| 2148 | if( !rndrer ) return; |
| 2149 | rndr.make = *rndrer; |
| 2150 | rndr.nBlobCache = 0; |
| 2151 | rndr.refs = empty_blob; |
| 2152 | for(i=0; i<256; i++) rndr.active_char[i] = 0; |
| 2153 | if( (rndr.make.emphasis |
| 2154 | || rndr.make.double_emphasis |
| 2155 | || rndr.make.triple_emphasis) |
| 2156 | && rndr.make.emph_chars |
| @@ -2260,8 +2213,9 @@ | |
| 2213 | blob_reset(&lr[i].id); |
| 2214 | blob_reset(&lr[i].link); |
| 2215 | blob_reset(&lr[i].title); |
| 2216 | } |
| 2217 | blob_reset(&rndr.refs); |
| 2218 | for(i=0; i<rndr.nBlobCache; i++){ |
| 2219 | fossil_free(rndr.aBlobCache[i]); |
| 2220 | } |
| 2221 | } |
| 2222 |
-1
| --- src/markdown_html.c | ||
| +++ src/markdown_html.c | ||
| @@ -510,11 +510,10 @@ | ||
| 510 | 510 | /* low level elements */ |
| 511 | 511 | 0, /* entities are copied verbatim */ |
| 512 | 512 | html_normal_text, |
| 513 | 513 | |
| 514 | 514 | /* misc. parameters */ |
| 515 | - 64, /* maximum stack */ | |
| 516 | 515 | "*_", /* emphasis characters */ |
| 517 | 516 | 0 /* opaque data */ |
| 518 | 517 | }; |
| 519 | 518 | html_renderer.opaque = output_title; |
| 520 | 519 | if( output_title ) blob_reset(output_title); |
| 521 | 520 |
| --- src/markdown_html.c | |
| +++ src/markdown_html.c | |
| @@ -510,11 +510,10 @@ | |
| 510 | /* low level elements */ |
| 511 | 0, /* entities are copied verbatim */ |
| 512 | html_normal_text, |
| 513 | |
| 514 | /* misc. parameters */ |
| 515 | 64, /* maximum stack */ |
| 516 | "*_", /* emphasis characters */ |
| 517 | 0 /* opaque data */ |
| 518 | }; |
| 519 | html_renderer.opaque = output_title; |
| 520 | if( output_title ) blob_reset(output_title); |
| 521 |
| --- src/markdown_html.c | |
| +++ src/markdown_html.c | |
| @@ -510,11 +510,10 @@ | |
| 510 | /* low level elements */ |
| 511 | 0, /* entities are copied verbatim */ |
| 512 | html_normal_text, |
| 513 | |
| 514 | /* misc. parameters */ |
| 515 | "*_", /* emphasis characters */ |
| 516 | 0 /* opaque data */ |
| 517 | }; |
| 518 | html_renderer.opaque = output_title; |
| 519 | if( output_title ) blob_reset(output_title); |
| 520 |