redo the whole flags dealie as an opaque blob

This commit is contained in:
david parsons
2019-12-07 22:49:52 -08:00
parent d74c180a8c
commit b9e867b574
18 changed files with 622 additions and 359 deletions
+1 -1
View File
@@ -50,7 +50,7 @@ Cswrite(Cstring *iot, char *bfr, int size)
/* reparse() into a cstring
*/
void
Csreparse(Cstring *iot, char *buf, int size, mkd_flag_t flags)
Csreparse(Cstring *iot, char *buf, int size, mkd_flag_t* flags)
{
MMIOT f;
___mkd_initmmiot(&f, 0);
+3 -3
View File
@@ -115,8 +115,8 @@ dumptree(Paragraph *pp, Stack *sp, FILE *f)
if ( pp->ident )
d += fprintf(f, " %s", pp->ident);
if ( pp->flags )
d += fprintf(f, " %x", pp->flags);
if ( pp->para_flags )
d += fprintf(f, " %x", pp->para_flags);
if ( pp->align > 1 )
d += fprintf(f, ", <%s>", Begin[pp->align]);
@@ -141,7 +141,7 @@ dumptree(Paragraph *pp, Stack *sp, FILE *f)
int
mkd_dump(Document *doc, FILE *out, mkd_flag_t flags, char *title)
mkd_dump(Document *doc, FILE *out, mkd_flag_t *flags, char *title)
{
Stack stack;
+17 -4
View File
@@ -2,7 +2,7 @@
#include "markdown.h"
struct flagnames {
mkd_flag_t flag;
int flag;
char *name;
};
@@ -41,8 +41,15 @@ static struct flagnames flagnames[] = {
#define NR(x) (sizeof x/sizeof x[0])
int
mkd_flag_isset(mkd_flag_t *flags, int i)
{
return flags ? is_flag_set(flags, i) : 0;
}
void
mkd_flags_are(FILE *f, mkd_flag_t flags, int htmlplease)
mkd_flags_are(FILE *f, mkd_flag_t* flags, int htmlplease)
{
int i;
int not, set, even=1;
@@ -51,7 +58,7 @@ mkd_flags_are(FILE *f, mkd_flag_t flags, int htmlplease)
if ( htmlplease )
fprintf(f, "<table class=\"mkd_flags_are\">\n");
for (i=0; i < NR(flagnames); i++) {
set = flags & flagnames[i].flag;
set = mkd_flag_isset(flags, flagnames[i].flag);
name = flagnames[i].name;
if ( not = (*name == '!') ) {
++name;
@@ -88,5 +95,11 @@ void
mkd_mmiot_flags(FILE *f, MMIOT *m, int htmlplease)
{
if ( m )
mkd_flags_are(f, m->flags, htmlplease);
mkd_flags_are(f, &(m->flags), htmlplease);
}
void
mkd_init_flags(mkd_flag_t *p)
{
memset(p, 0, sizeof(*p));
}
+70 -59
View File
@@ -209,14 +209,16 @@ Qem(MMIOT *f, char c, int count)
/* generate html from a markup fragment
*/
void
___mkd_reparse(char *bfr, int size, mkd_flag_t flags, MMIOT *f, char *esc)
___mkd_reparse(char *bfr, int size, mkd_flag_t* flags, MMIOT *f, char *esc)
{
MMIOT sub;
struct escaped e;
___mkd_initmmiot(&sub, f->footnotes);
sub.flags = f->flags | flags;
COPY_FLAGS(sub.flags,f->flags);
if ( flags )
OR_FLAGS(&sub.flags, flags);
sub.cb = f->cb;
sub.ref_prefix = f->ref_prefix;
@@ -473,7 +475,7 @@ linkyurl(MMIOT *f, int image, Footnote *p)
if ( c == '<' ) {
pull(f);
if ( !is_flag_set(f->flags, MKD_1_COMPAT) )
if ( !is_flag_set(&f->flags, MKD_1_COMPAT) )
return linkybroket(f,image,p);
mayneedtotrim=1;
}
@@ -546,15 +548,15 @@ typedef struct linkytype {
int WxH; /* this tag allows width x height arguments */
char *text_pfx; /* text prefix (eg: ">" */
char *text_sfx; /* text suffix (eg: "</a>" */
int flags; /* reparse flags */
mkd_flag_t flags; /* reparse flags */
int kind; /* tag is url or something else? */
#define IS_URL 0x01
} linkytype;
static linkytype imaget = { 0, 0, "<img src=\"", "\"",
1, " alt=\"", "\" />", MKD_NOIMAGE|MKD_TAGTEXT, IS_URL };
1, " alt=\"", "\" />", { { [MKD_NOIMAGE] = 1, [MKD_TAGTEXT] = 1} }, IS_URL };
static linkytype linkt = { 0, 0, "<a href=\"", "\"",
0, ">", "</a>", MKD_NOLINKS, IS_URL };
0, ">", "</a>", { {[MKD_NOLINKS] = 1} }, IS_URL };
/*
* pseudo-protocols for [][];
@@ -564,11 +566,11 @@ static linkytype linkt = { 0, 0, "<a href=\"", "\"",
* raw: just dump the link without any processing
*/
static linkytype specials[] = {
{ "id:", 3, "<span id=\"", "\"", 0, ">", "</span>", 0, 0 },
{ "raw:", 4, 0, 0, 0, 0, 0, MKD_NOHTML, 0 },
{ "lang:", 5, "<span lang=\"", "\"", 0, ">", "</span>", 0, 0 },
{ "abbr:", 5, "<abbr title=\"", "\"", 0, ">", "</abbr>", 0, 0 },
{ "class:", 6, "<span class=\"", "\"", 0, ">", "</span>", 0, 0 },
{ "id:", 3, "<span id=\"", "\"", 0, ">", "</span>", {}, 0 },
{ "raw:", 4, 0, 0, 0, 0, 0, { { [MKD_NOHTML] = 1 } }, 0 },
{ "lang:", 5, "<span lang=\"", "\"", 0, ">", "</span>", {}, 0 },
{ "abbr:", 5, "<abbr title=\"", "\"", 0, ">", "</abbr>", {}, 0 },
{ "class:", 6, "<span class=\"", "\"", 0, ">", "</span>", {}, 0 },
} ;
#define NR(x) (sizeof x / sizeof x[0])
@@ -596,7 +598,7 @@ printlinkyref(MMIOT *f, linkytype *tag, char *link, int size)
{
char *edit;
if ( is_flag_set(f->flags, IS_LABEL) )
if ( is_flag_set(&f->flags, IS_LABEL) )
return;
Qstring(tag->link_pfx, f);
@@ -609,8 +611,12 @@ printlinkyref(MMIOT *f, linkytype *tag, char *link, int size)
else
puturl(link + tag->szpat, size - tag->szpat, f, 0);
}
else
___mkd_reparse(link + tag->szpat, size - tag->szpat, MKD_TAGTEXT, f, 0);
else {
mkd_flag_t tagtext;
mkd_init_flags(&tagtext);
set_mkd_flag(&tagtext, MKD_TAGTEXT);
___mkd_reparse(link + tag->szpat, size - tag->szpat, &tagtext, f, 0);
}
Qstring(tag->link_sfx, f);
@@ -638,13 +644,13 @@ MMIOT *p;
static int
extra_linky(MMIOT *f, Cstring text, Footnote *ref)
{
if ( ref->flags & REFERENCED )
if ( ref->fn_flags & REFERENCED )
return 0;
if ( f->flags & IS_LABEL )
___mkd_reparse(T(text), S(text), linkt.flags, f, 0);
if ( is_flag_set(&f->flags,IS_LABEL) )
___mkd_reparse(T(text), S(text), &(linkt.flags), f, 0);
else {
ref->flags |= REFERENCED;
ref->fn_flags |= REFERENCED;
ref->refnumber = ++ f->footnotes->reference;
Qprintf(f, "<sup id=\"%sref:%d\"><a href=\"#%s:%d\" rel=\"footnote\">%d</a></sup>",
p_or_nothing(f), ref->refnumber,
@@ -686,15 +692,17 @@ static int
linkyformat(MMIOT *f, Cstring text, int image, Footnote *ref)
{
linkytype *tag;
static mkd_flag_t tagtext = { {[MKD_TAGTEXT] = 1} };
mkd_flag_t flags;
if ( image )
tag = &imaget;
else if ( tag = pseudo(ref->link) ) {
if ( is_flag_set(f->flags, MKD_NO_EXT) || is_flag_set(f->flags, MKD_SAFELINK) )
if ( is_flag_set(&f->flags, MKD_NO_EXT) || is_flag_set(&f->flags, MKD_SAFELINK) )
return 0;
}
else if ( is_flag_set(f->flags, MKD_SAFELINK) && !safelink(ref->link) )
else if ( is_flag_set(&f->flags, MKD_SAFELINK) && !safelink(ref->link) )
/* if MKD_SAFELINK, only accept links that are local or
* a well-known protocol
*/
@@ -702,11 +710,12 @@ linkyformat(MMIOT *f, Cstring text, int image, Footnote *ref)
else
tag = &linkt;
if ( f->flags & tag->flags )
COPY_FLAGS(flags, f->flags);
if ( AND_FLAGS(&flags, &tag->flags) )
return 0;
if ( is_flag_set(f->flags, IS_LABEL) )
___mkd_reparse(T(text), S(text), tag->flags, f, 0);
if ( is_flag_set(&f->flags, IS_LABEL) )
___mkd_reparse(T(text), S(text), &(tag->flags), f, 0);
else if ( tag->link_pfx ) {
printlinkyref(f, tag, T(ref->link), S(ref->link));
@@ -717,12 +726,12 @@ linkyformat(MMIOT *f, Cstring text, int image, Footnote *ref)
if ( S(ref->title) ) {
Qstring(" title=\"", f);
___mkd_reparse(T(ref->title), S(ref->title), MKD_TAGTEXT, f, 0);
___mkd_reparse(T(ref->title), S(ref->title), &tagtext, f, 0);
Qchar('"', f);
}
Qstring(tag->text_pfx, f);
___mkd_reparse(T(text), S(text), tag->flags, f, 0);
___mkd_reparse(T(text), S(text), &(tag->flags), f, 0);
Qstring(tag->text_sfx, f);
}
else
@@ -769,9 +778,9 @@ linkylinky(int image, MMIOT *f)
* require a second []
*/
mmiotseek(f, implicit_mark);
goodlink = !is_flag_set(f->flags, MKD_1_COMPAT);
goodlink = !is_flag_set(&f->flags, MKD_1_COMPAT);
if ( is_flag_set(f->flags, MKD_EXTRA_FOOTNOTE) && (!image) && S(name) && T(name)[0] == '^' )
if ( is_flag_set(&f->flags, MKD_EXTRA_FOOTNOTE) && (!image) && S(name) && T(name)[0] == '^' )
extra_footnote = 1;
}
@@ -901,13 +910,14 @@ code(MMIOT *f, char *s, int length)
cputc(c, f);
} /* code */
/* delspan() -- write out a chunk of text, blocking with <del>...</del>
*/
static void
delspan(MMIOT *f, int size)
{
Qstring("<del>", f);
___mkd_reparse(cursor(f)-1, size, 0, f, 0);
___mkd_reparse(cursor(f)-1, size, NULL, f, 0);
Qstring("</del>", f);
}
@@ -937,12 +947,12 @@ forbidden_tag(MMIOT *f)
{
int c = toupper(peek(f, 1));
if ( is_flag_set(f->flags, MKD_NOHTML) )
if ( is_flag_set(&f->flags, MKD_NOHTML) )
return 1;
if ( c == 'A' && is_flag_set(f->flags, MKD_NOLINKS) && !isthisalnum(f,2) )
if ( c == 'A' && is_flag_set(&f->flags, MKD_NOLINKS) && !isthisalnum(f,2) )
return 1;
if ( c == 'I' && is_flag_set(f->flags, MKD_NOIMAGE)
if ( c == 'I' && is_flag_set(&f->flags, MKD_NOIMAGE)
&& strncasecmp(cursor(f)+1, "MG", 2) == 0
&& !isthisalnum(f,4) )
return 1;
@@ -989,7 +999,7 @@ process_possible_link(MMIOT *f, int size)
int mailto = 0;
char *text = cursor(f);
if ( is_flag_set(f->flags, MKD_NOLINKS) ) return 0;
if ( is_flag_set(&f->flags, MKD_NOLINKS) ) return 0;
if ( (size > 7) && strncasecmp(text, "mailto:", 7) == 0 ) {
/* if it says it's a mailto, it's a mailto -- who am
@@ -1036,7 +1046,7 @@ maybe_tag_or_link(MMIOT *f)
int c, size;
int maybetag = 1;
if ( is_flag_set(f->flags, MKD_TAGTEXT) )
if ( is_flag_set(&f->flags, MKD_TAGTEXT) )
return 0;
for ( size=0; (c = peek(f, size+1)) != '>'; size++) {
@@ -1050,7 +1060,7 @@ maybe_tag_or_link(MMIOT *f)
else if ( isspace(c) )
break;
else if ( ! (c == '/'
|| (is_flag_set(f->flags, MKD_GITHUBTAGS) && (c == '-' || c == '_'))
|| (is_flag_set(&f->flags, MKD_GITHUBTAGS) && (c == '-' || c == '_'))
|| isalnum(c) ) )
maybetag=0;
}
@@ -1204,9 +1214,9 @@ smartypants(int c, int *flags, MMIOT *f)
{
int i;
if ( is_flag_set(f->flags, MKD_NOPANTS)
|| is_flag_set(f->flags, MKD_TAGTEXT)
|| is_flag_set(f->flags, IS_LABEL) )
if ( is_flag_set(&f->flags, MKD_NOPANTS)
|| is_flag_set(&f->flags, MKD_TAGTEXT)
|| is_flag_set(&f->flags, IS_LABEL) )
return 0;
for ( i=0; i < NRSMART; i++)
@@ -1235,7 +1245,7 @@ smartypants(int c, int *flags, MMIOT *f)
break;
else if ( c == '\'' && peek(f, j+1) == '\'' ) {
Qstring("&ldquo;", f);
___mkd_reparse(cursor(f)+1, j-2, 0, f, 0);
___mkd_reparse(cursor(f)+1, j-2, NULL, f, 0);
Qstring("&rdquo;", f);
shift(f,j+1);
return 1;
@@ -1298,7 +1308,7 @@ tickhandler(MMIOT *f, int tickchar, int minticks, int allow_space, spanhandler s
return 0;
}
#define tag_text(f) is_flag_set(f->flags, MKD_TAGTEXT)
#define tag_text(f) is_flag_set(&((f)->flags), MKD_TAGTEXT)
static void
@@ -1308,8 +1318,9 @@ text(MMIOT *f)
int rep;
int smartyflags = 0;
while (1) {
if ( is_flag_set(f->flags, MKD_AUTOLINK) && isalpha(peek(f,1)) && !tag_text(f) )
if ( is_flag_set(&f->flags, MKD_AUTOLINK) && isalpha(peek(f,1)) && !tag_text(f) )
maybe_autolink(f);
c = pull(f);
@@ -1351,8 +1362,8 @@ text(MMIOT *f)
Qchar(c, f);
break;
/* A^B -> A<sup>B</sup> */
case '^': if ( is_flag_set(f->flags, MKD_NOSUPERSCRIPT)
|| is_flag_set(f->flags, MKD_TAGTEXT)
case '^': if ( is_flag_set(&f->flags, MKD_NOSUPERSCRIPT)
|| is_flag_set(&f->flags, MKD_TAGTEXT)
|| (f->last == 0)
|| ((ispunct(f->last) || isspace(f->last))
&& f->last != ')')
@@ -1383,13 +1394,13 @@ text(MMIOT *f)
shift(f,len);
}
Qstring("<sup>",f);
___mkd_reparse(sup, len, 0, f, "()");
___mkd_reparse(sup, len, NULL, f, "()");
Qstring("</sup>", f);
}
break;
case '_':
/* Underscores don't count if they're in the middle of a word */
if ( !is_flag_set(f->flags, MKD_NORELAXED)
if ( !is_flag_set(&f->flags, MKD_NORELAXED)
&& isthisalnum(f,-1) && isthisalnum(f,1) ) {
Qchar(c, f);
break;
@@ -1411,8 +1422,8 @@ text(MMIOT *f)
}
break;
case '~': if ( is_flag_set(f->flags, MKD_NOSTRIKETHROUGH)
|| is_flag_set(f->flags, MKD_TAGTEXT)
case '~': if ( is_flag_set(&f->flags, MKD_NOSTRIKETHROUGH)
|| is_flag_set(&f->flags, MKD_TAGTEXT)
|| ! tickhandler(f,c,2,0, delspan) )
Qchar(c, f);
break;
@@ -1435,7 +1446,7 @@ text(MMIOT *f)
}
break;
case '^': if ( is_flag_set(f->flags, MKD_NOSUPERSCRIPT) ) {
case '^': if ( is_flag_set(&f->flags, MKD_NOSUPERSCRIPT) ) {
Qchar('\\', f);
shift(f,-1);
break;
@@ -1444,7 +1455,7 @@ text(MMIOT *f)
break;
case ':': case '|':
if ( is_flag_set(f->flags, MKD_NOTABLES) ) {
if ( is_flag_set(&f->flags, MKD_NOTABLES) ) {
Qchar('\\', f);
shift(f,-1);
break;
@@ -1456,7 +1467,7 @@ text(MMIOT *f)
break;
case '[':
case '(': if ( is_flag_set(f->flags, MKD_LATEX)
case '(': if ( is_flag_set(&f->flags, MKD_LATEX)
&& mathhandler(f, '\\', (c =='(')?')':']') )
break;
/* else fall through to default */
@@ -1486,7 +1497,7 @@ text(MMIOT *f)
Qchar(c, f);
break;
case '$': if ( is_flag_set(f->flags, MKD_LATEX) && (peek(f, 1) == '$') ) {
case '$': if ( is_flag_set(&f->flags, MKD_LATEX) && (peek(f, 1) == '$') ) {
pull(f);
if ( mathhandler(f, '$', '$') )
break;
@@ -1509,16 +1520,16 @@ text(MMIOT *f)
static void
printheader(Paragraph *pp, MMIOT *f)
{
if ( is_flag_set(f->flags, MKD_IDANCHOR) ) {
if ( is_flag_set(&f->flags, MKD_IDANCHOR) ) {
Qprintf(f, "<h%d", pp->hnumber);
if ( is_flag_set(f->flags, MKD_TOC) ) {
if ( is_flag_set(&f->flags, MKD_TOC) ) {
Qstring(" id=\"", f);
Qanchor(pp->text, f);
Qchar('"', f);
}
Qchar('>', f);
} else {
if ( is_flag_set(f->flags, MKD_TOC) ) {
if ( is_flag_set(&f->flags, MKD_TOC) ) {
Qstring("<a name=\"", f);
Qanchor(pp->text, f);
Qstring("\"></a>\n", f);
@@ -1566,7 +1577,7 @@ splat(Line *p, char *block, Istring align, int force, MMIOT *f)
Qprintf(f, "<%s%s>",
block,
alignments[ (colno < S(align)) ? T(align)[colno] : a_NONE ]);
___mkd_reparse(T(p->text)+first, idx-first, 0, f, "|");
___mkd_reparse(T(p->text)+first, idx-first, NULL, f, "|");
Qprintf(f, "</%s>\n", block);
idx++;
colno++;
@@ -1777,7 +1788,7 @@ htmlify_paragraphs(Paragraph *p, MMIOT *f)
static void
li_htmlify(Paragraph *p, char *arguments, mkd_flag_t flags, MMIOT *f)
li_htmlify(Paragraph *p, char *arguments, int flags, MMIOT *f)
{
___mkd_emblock(f);
@@ -1832,7 +1843,7 @@ definitionlist(Paragraph *p, MMIOT *f)
for ( ; p ; p = p->next) {
for ( tag = p->text; tag; tag = tag->next ) {
Qstring("<dt>", f);
___mkd_reparse(T(tag->text), S(tag->text), 0, f, 0);
___mkd_reparse(T(tag->text), S(tag->text), NULL, f, 0);
Qstring("</dt>\n", f);
}
@@ -1855,7 +1866,7 @@ listdisplay(int typ, Paragraph *p, MMIOT* f)
Qprintf(f, ">\n");
for ( ; p ; p = p->next ) {
li_htmlify(p->down, p->ident, p->flags, f);
li_htmlify(p->down, p->ident, p->para_flags, f);
Qchar('\n', f);
}
@@ -1938,7 +1949,7 @@ mkd_extra_footnotes(MMIOT *m)
for ( i=1; i <= m->footnotes->reference; i++ ) {
for ( j=0; j < S(m->footnotes->note); j++ ) {
t = &T(m->footnotes->note)[j];
if ( (t->refnumber == i) && (t->flags & REFERENCED) ) {
if ( (t->refnumber == i) && (t->fn_flags & REFERENCED) ) {
Csprintf(&m->out, "<li id=\"%s:%d\">\n",
p_or_nothing(m), t->refnumber);
htmlify(t->text, 0, 0, m);
@@ -1963,7 +1974,7 @@ mkd_document(Document *p, char **res)
if ( p && p->compiled ) {
if ( ! p->html ) {
htmlify(p->code, 0, 0, p->ctx);
if ( is_flag_set(p->ctx->flags, MKD_EXTRA_FOOTNOTE) )
if ( is_flag_set(&p->ctx->flags, MKD_EXTRA_FOOTNOTE) )
mkd_extra_footnotes(p->ctx);
p->html = 1;
size = S(p->ctx->out);
+5 -5
View File
@@ -21,7 +21,7 @@
typedef int (*getc_func)(void*);
Document *
gfm_populate(getc_func getc, void* ctx, int flags)
gfm_populate(getc_func getc, void* ctx, mkd_flag_t *flags)
{
Cstring line;
Document *a = __mkd_new_Document();
@@ -80,21 +80,21 @@ gfm_populate(getc_func getc, void* ctx, int flags)
/* convert a block of text into a linked list
*/
Document *
gfm_string(const char *buf, int len, mkd_flag_t flags)
gfm_string(const char *buf, int len, mkd_flag_t* flags)
{
struct string_stream about;
about.data = buf;
about.size = len;
return gfm_populate((getc_func)__mkd_io_strget, &about, flags & INPUT_MASK);
return gfm_populate((getc_func)__mkd_io_strget, &about, flags);
}
/* convert a file into a linked list
*/
Document *
gfm_in(FILE *f, mkd_flag_t flags)
gfm_in(FILE *f, mkd_flag_t* flags)
{
return gfm_populate((getc_func)fgetc, f, flags & INPUT_MASK);
return gfm_populate((getc_func)fgetc, f, flags);
}
+4 -2
View File
@@ -17,7 +17,7 @@ mkd_h1(Paragraph *p)
}
char *
mkd_h1_title(Document *doc, int flags)
mkd_h1_title(Document *doc, mkd_flag_t* flags)
{
Paragraph *title;
@@ -28,8 +28,10 @@ mkd_h1_title(Document *doc, int flags)
/* assert that a H1 header is one line long, so that's
* the only thing needed
*/
set_mkd_flag(flags, MKD_TAGTEXT);
size = mkd_line(T(title->text->text),
S(title->text->text), &generated, flags|MKD_TAGTEXT);
S(title->text->text), &generated, flags);
clear_mkd_flag(flags, MKD_TAGTEXT);
if ( size ) return generated;
}
return 0;
+37 -25
View File
@@ -168,7 +168,7 @@ int
main(int argc, char **argv)
{
int rc;
mkd_flag_t flags = 0;
mkd_flag_t flags;
int debug = 0;
int toc = 0;
int content = 1;
@@ -192,11 +192,13 @@ main(int argc, char **argv)
hoptset(&blob, argc, argv);
hopterr(&blob, 1);
if ( q = getenv("MARKDOWN_FLAGS") )
flags = strtol(q, 0, 0);
pgm = basename(argv[0]);
mkd_init_flags(&flags);
if ( q = getenv("MARKDOWN_FLAGS") )
mkd_set_flag_bitmap(&flags, strtol(q,0,0));
while ( opt=gethopt(&blob, opts, NROPTS) ) {
if ( opt == HOPTERR ) {
hoptusage(pgm, opts, NROPTS, "[file]");
@@ -213,19 +215,29 @@ main(int argc, char **argv)
break;
case 'E': urlflags = hoptarg(&blob);
break;
case 'F': if ( strcmp(hoptarg(&blob), "?") == 0 ) {
show_flags(0, 0);
case 'f': q = hoptarg(&blob);
if ( strcmp(q, "?") == 0 ) {
show_flags(1, version, 0);
exit(0);
}
else if ( strcmp(q, "??") == 0 ) {
show_flags(1, version, &flags);
exit(0);
}
else if ( q=mkd_set_flag_string(&flags, hoptarg(&blob)) )
complain("unknown option <%s>", q);
break;
case 'F': q = hoptarg(&blob);
if ( strcmp(q, "?") == 0 ) {
show_flags(0, 0, 0);
exit(0);
}
else if ( strcmp(q, "??") == 0 ) {
show_flags(0, version, &flags);
exit(0);
}
else
flags = strtol(hoptarg(&blob), 0, 0);
break;
case 'f': if ( strcmp(hoptarg(&blob), "?") == 0 ) {
show_flags(1, version);
exit(0);
}
else if ( q=set_flag(&flags, hoptarg(&blob)) )
complain("unknown option <%s>", q);
mkd_set_flag_bitmap(&flags,strtol(q, 0, 0));
break;
case 'G': github_flavoured = 1;
break;
@@ -238,7 +250,7 @@ main(int argc, char **argv)
case 't': text = hoptarg(&blob);
use_mkd_line = 1;
break;
case 'T': flags |= MKD_TOC;
case 'T': mkd_set_flag_num(&flags, MKD_TOC);
toc = 1;
break;
case 'C': extra_footnote_prefix = hoptarg(&blob);
@@ -255,18 +267,17 @@ main(int argc, char **argv)
case 'x': squash = 1;
break;
case 'X': use_e_codefmt = 1;
set_flag(&flags, "fencedcode");
mkd_set_flag_num(&flags, MKD_FENCEDCODE);
break;
}
}
if ( version ) {
printf("%s: discount %s%s", pgm, markdown_version,
with_html5 ? " +html5":"");
if ( version == 2 )
mkd_flags_are(stdout, flags, 0);
if ( version >= 3 )
printf(" MARKDOWN_FLAGS=0x%08x", flags);
mkd_flags_are(stdout, &flags, 0);
putchar('\n');
exit(0);
}
@@ -278,11 +289,11 @@ main(int argc, char **argv)
mkd_with_html5_tags();
if ( use_mkd_line )
rc = mkd_generateline( text, strlen(text), stdout, flags);
rc = mkd_generateline( text, strlen(text), stdout, &flags);
else {
if ( text ) {
doc = github_flavoured ? gfm_string(text, strlen(text), flags)
: mkd_string(text, strlen(text), flags) ;
doc = github_flavoured ? gfm_string(text, strlen(text), &flags)
: mkd_string(text, strlen(text), &flags) ;
if ( !doc ) {
perror(text);
@@ -295,7 +306,8 @@ main(int argc, char **argv)
exit(1);
}
doc = github_flavoured ? gfm_in(stdin,flags) : mkd_in(stdin,flags);
doc = github_flavoured ? gfm_in(stdin,&flags)
: mkd_in(stdin,&flags);
if ( !doc ) {
perror(argc ? argv[0] : "stdin");
exit(1);
@@ -319,10 +331,10 @@ main(int argc, char **argv)
mkd_ref_prefix(doc, extra_footnote_prefix);
if ( debug )
rc = mkd_dump(doc, stdout, 0, argc ? basename(argv[0]) : "stdin");
rc = mkd_dump(doc, stdout, &flags, argc ? basename(argv[0]) : "stdin");
else {
rc = 1;
if ( mkd_compile(doc, flags) ) {
if ( mkd_compile(doc, &flags) ) {
rc = 0;
if ( styles )
mkd_generatecss(doc, stdout);
+25 -12
View File
@@ -37,13 +37,21 @@ char **argv;
MMIOT *doc;
char *q;
int version = 0;
int ret;
mkd_flag_t flags = 0;
int ret, i;
DWORD bits;
mkd_flag_t flags;
struct h_opt *opt;
struct h_context blob;
if ( (q = getenv("MARKDOWN_FLAGS")) )
flags = strtol(q, 0, 0);
mkd_init_flags(&flags);
if ( (q = getenv("MARKDOWN_FLAGS")) ) {
bits = strtol(q, 0, 0);
for ( i=0; i < 8*sizeof(bits); i++)
if ( bits & (1<<i) )
mkd_set_flag_num(&flags, i);
}
hoptset(&blob, argc, argv);
hopterr(&blob, 1);
@@ -57,17 +65,22 @@ char **argv;
case 'V': version++;
break;
case 'F': if ( strcmp(hoptarg(&blob), "?") == 0 ) {
show_flags(0,0);
show_flags(0,0,0);
exit(0);
}
else
flags = strtol(hoptarg(&blob), 0, 0);
else {
bits = strtol(hoptarg(&blob), 0, 0);
for (i=0; i < 8*sizeof(bits); i++)
if ( bits & (1<<i) )
mkd_set_flag_num(&flags, i);
}
break;
case 'f': if ( strcmp(hoptarg(&blob), "?") == 0 ) {
show_flags(1,version);
show_flags(1,version,0);
exit(0);
}
else if ( q = set_flag(&flags, hoptarg(&blob)) )
else if ( q = mkd_set_flag_string(&flags, hoptarg(&blob)) )
fprintf(stderr, "unknown option <%s>\n", q);
break;
}
@@ -79,7 +92,7 @@ char **argv;
if ( version ) {
printf("%s: discount %s", pgm, markdown_version);
if ( version > 1 )
mkd_flags_are(stdout, flags, 0);
mkd_flags_are(stdout, &flags, 0);
putchar('\n');
exit(0);
}
@@ -89,12 +102,12 @@ char **argv;
exit(1);
}
if ( (doc = mkd_in(stdin, flags)) == 0 ) {
if ( (doc = mkd_in(stdin, &flags)) == 0 ) {
perror( (argc > 1) ? argv[1] : "stdin" );
exit(1);
}
ret = mkd_xhtmlpage(doc, flags, stdout);
ret = mkd_xhtmlpage(doc, &flags, stdout);
mkd_cleanup(doc);
+86 -50
View File
@@ -178,7 +178,7 @@ splitline(Line *t, int cutpoint)
}
}
#define UNCHECK(l) ((l)->flags &= ~CHECKED)
#define UNCHECK(l) ((l)->line_flags &= ~CHECKED)
#define UNLESS_FENCED(t) if (fenced) { \
other = 1; l->count += (c == ' ' ? 0 : -1); \
@@ -189,7 +189,7 @@ splitline(Line *t, int cutpoint)
* types.
*/
static void
checkline(Line *l, mkd_flag_t flags)
checkline(Line *l, mkd_flag_t *flags)
{
int eol, i;
int dashes = 0, spaces = 0,
@@ -197,7 +197,7 @@ checkline(Line *l, mkd_flag_t flags)
stars = 0, tildes = 0, other = 0,
backticks = 0, fenced = 0;
l->flags |= CHECKED;
l->line_flags |= CHECKED;
l->kind = chk_text;
l->count = 0;
@@ -381,9 +381,9 @@ iscode(Line *t)
static inline int
ishr(Line *t, mkd_flag_t flags)
ishr(Line *t, mkd_flag_t *flags)
{
if ( ! (t->flags & CHECKED) )
if ( ! (t->line_flags & CHECKED) )
checkline(t, flags);
if ( t->count > 2 )
@@ -393,7 +393,7 @@ ishr(Line *t, mkd_flag_t flags)
static int
issetext(Line *t, int *htyp, mkd_flag_t flags)
issetext(Line *t, int *htyp, mkd_flag_t *flags)
{
Line *n;
@@ -402,7 +402,7 @@ issetext(Line *t, int *htyp, mkd_flag_t flags)
*/
if ( (n = t->next) ) {
if ( !(n->flags & CHECKED) )
if ( !(n->line_flags & CHECKED) )
checkline(n, flags);
if ( n->kind == chk_dash || n->kind == chk_equal ) {
@@ -415,7 +415,7 @@ issetext(Line *t, int *htyp, mkd_flag_t flags)
static int
ishdr(Line *t, int *htyp, mkd_flag_t flags)
ishdr(Line *t, int *htyp, mkd_flag_t *flags)
{
/* ANY leading `#`'s make this into an ETX header
*/
@@ -431,7 +431,7 @@ ishdr(Line *t, int *htyp, mkd_flag_t flags)
static inline int
end_of_block(Line *t, mkd_flag_t flags)
end_of_block(Line *t, mkd_flag_t *flags)
{
int dummy;
@@ -443,7 +443,7 @@ end_of_block(Line *t, mkd_flag_t flags)
static Line*
is_discount_dt(Line *t, int *clip, mkd_flag_t flags)
is_discount_dt(Line *t, int *clip, mkd_flag_t *flags)
{
if ( is_flag_set(flags, MKD_DLDISCOUNT)
&& t
@@ -472,7 +472,7 @@ is_extra_dd(Line *t)
static Line*
is_extra_dt(Line *t, int *clip, mkd_flag_t flags)
is_extra_dt(Line *t, int *clip, mkd_flag_t* flags)
{
if ( is_flag_set(flags, MKD_DLEXTRA)
&& t
@@ -496,7 +496,7 @@ is_extra_dt(Line *t, int *clip, mkd_flag_t flags)
static Line*
isdefinition(Line *t, int *clip, int *kind, mkd_flag_t flags)
isdefinition(Line *t, int *clip, int *kind, mkd_flag_t *flags)
{
Line *ret;
@@ -510,7 +510,7 @@ isdefinition(Line *t, int *clip, int *kind, mkd_flag_t flags)
static int
islist(Line *t, int *clip, mkd_flag_t flags, int *list_type)
islist(Line *t, int *clip, mkd_flag_t *flags, int *list_type)
{
int i, j;
char *q;
@@ -518,7 +518,7 @@ islist(Line *t, int *clip, mkd_flag_t flags, int *list_type)
if ( end_of_block(t, flags) )
return 0;
if ( is_flag_set(flags, MKD_DLIST) && isdefinition(t,clip,list_type,flags) )
if ( (is_flag_set(flags, MKD_DLEXTRA)||is_flag_set(flags, MKD_DLDISCOUNT)) && isdefinition(t,clip,list_type,flags) )
return DL;
if ( strchr("*-+", T(t->text)[t->dle]) && isspace(T(t->text)[t->dle+1]) ) {
@@ -623,12 +623,12 @@ codeblock(Paragraph *p)
static int
iscodefence(Line *r, int size, line_type kind, mkd_flag_t flags)
iscodefence(Line *r, int size, line_type kind, mkd_flag_t *flags)
{
if ( !is_flag_set(flags, MKD_FENCEDCODE) )
return 0;
if ( !(r->flags & CHECKED) )
if ( !(r->line_flags & CHECKED) )
checkline(r, flags);
if ( kind )
@@ -639,7 +639,7 @@ iscodefence(Line *r, int size, line_type kind, mkd_flag_t flags)
static Paragraph *
fencedcodeblock(ParagraphRoot *d, Line **ptr, mkd_flag_t flags)
fencedcodeblock(ParagraphRoot *d, Line **ptr, mkd_flag_t *flags)
{
Line *first, *r;
Paragraph *ret;
@@ -694,7 +694,7 @@ centered(Line *first, Line *last)
static int
endoftextblock(Line *t, int toplevelblock, mkd_flag_t flags)
endoftextblock(Line *t, int toplevelblock, mkd_flag_t *flags)
{
int z;
@@ -714,7 +714,7 @@ endoftextblock(Line *t, int toplevelblock, mkd_flag_t flags)
static Line *
textblock(Paragraph *p, int toplevel, mkd_flag_t flags)
textblock(Paragraph *p, int toplevel, mkd_flag_t *flags)
{
Line *t, *next;
@@ -749,7 +749,7 @@ szmarkerclass(char *p)
#define iscsschar(c) (isalpha(c) || (c == '-') || (c == '_') )
static int
isdivmarker(Line *p, int start, mkd_flag_t flags)
isdivmarker(Line *p, int start, mkd_flag_t *flags)
{
char *s;
int last, i;
@@ -788,7 +788,7 @@ isdivmarker(Line *p, int start, mkd_flag_t flags)
* way the markdown sample web form at Daring Fireball works.
*/
static Line *
quoteblock(Paragraph *p, mkd_flag_t flags)
quoteblock(Paragraph *p, mkd_flag_t *flags)
{
Line *t, *q;
int qp;
@@ -848,7 +848,7 @@ typedef int (*linefn)(Line *);
* marker, but multiple paragraphs need to start with a 4-space indent.
*/
static Line *
listitem(Paragraph *p, int indent, mkd_flag_t flags, linefn check)
listitem(Paragraph *p, int indent, mkd_flag_t *flags, linefn check)
{
Line *t, *q;
int clip = indent;
@@ -872,9 +872,9 @@ listitem(Paragraph *p, int indent, mkd_flag_t flags, linefn check)
if ( ischeck != CHECK_NOT ) {
__mkd_trim_line(t, 3);
p->flags |= GITHUB_CHECK;
p->para_flags |= GITHUB_CHECK;
if ( ischeck == CHECK_YES )
p->flags |= IS_CHECKED;
p->para_flags |= IS_CHECKED;
}
firstpara = 0;
}
@@ -930,7 +930,7 @@ definition_block(Paragraph *top, int clip, MMIOT *f, int kind)
while (( labels = q )) {
if ( (q = isdefinition(labels, &z, &kind, f->flags)) == 0 )
if ( (q = isdefinition(labels, &z, &kind, &(f->flags))) == 0 )
break;
if ( (text = skipempty(q->next)) == 0 )
@@ -950,7 +950,7 @@ definition_block(Paragraph *top, int clip, MMIOT *f, int kind)
dd_block:
p = Pp(&d, text, LISTITEM);
text = listitem(p, clip, f->flags, (kind==2) ? is_extra_dd : 0);
text = listitem(p, clip, &(f->flags), (kind==2) ? is_extra_dd : 0);
p->down = compile(p->text, 0, f);
p->text = labels; labels = 0;
@@ -988,7 +988,7 @@ enumerated_block(Paragraph *top, int clip, MMIOT *f, int list_class)
while (( text = q )) {
p = Pp(&d, text, LISTITEM);
text = listitem(p, clip, f->flags, 0);
text = listitem(p, clip, &(f->flags), 0);
p->down = compile(p->text, 0, f);
p->text = 0;
@@ -996,7 +996,7 @@ enumerated_block(Paragraph *top, int clip, MMIOT *f, int list_class)
if ( para && p->down ) p->down->align = PARA;
if ( (q = skipempty(text)) == 0
|| islist(q, &clip, f->flags, &z) != list_class )
|| islist(q, &clip, &(f->flags), &z) != list_class )
break;
if ( para = (q != text) ) {
@@ -1064,7 +1064,7 @@ addfootnote(Line *p, MMIOT* f)
CREATE(foot->link);
CREATE(foot->title);
foot->text = 0;
foot->flags = foot->height = foot->width = 0;
foot->fn_flags = foot->height = foot->width = 0;
/* keep the footnote label */
for (j=i=p->dle+1; T(p->text)[j] != ']'; j++)
@@ -1075,12 +1075,12 @@ addfootnote(Line *p, MMIOT* f)
/* consume the closing ]: */
j = nextnonblank(p, j+2);
if ( is_flag_set(f->flags, MKD_EXTRA_FOOTNOTE) && (T(foot->tag)[0] == '^') ) {
if ( is_flag_set(&(f->flags), MKD_EXTRA_FOOTNOTE) && (T(foot->tag)[0] == '^') ) {
/* markdown extra footnote: All indented lines past this point;
* the first line includes the footnote reference, so we need to
* snip that out as we go.
*/
foot->flags |= EXTRA_FOOTNOTE;
foot->fn_flags |= EXTRA_FOOTNOTE;
__mkd_trim_line(p,j);
np = extrablock(p);
@@ -1197,14 +1197,14 @@ compile_document(Line *ptr, MMIOT *f)
int previous_was_break = 1;
while ( ptr ) {
if ( !is_flag_set(f->flags, MKD_NOHTML) && (tag = isopentag(ptr)) ) {
if ( !is_flag_set(&(f->flags), MKD_NOHTML) && (tag = isopentag(ptr)) ) {
int blocktype;
/* If we encounter a html/style block, compile and save all
* of the cached source BEFORE processing the html/style.
*/
uncache(&source, &d, f);
if (is_flag_set(f->flags, MKD_NOSTYLE) )
if (is_flag_set(&(f->flags), MKD_NOSTYLE) )
blocktype = HTML;
else
blocktype = strcmp(tag->id, "STYLE") == 0 ? STYLE : HTML;
@@ -1225,9 +1225,9 @@ compile_document(Line *ptr, MMIOT *f)
ptr = consume(addfootnote(ptr, f), &eaten);
previous_was_break = 1;
}
else if ( previous_was_break && iscodefence(ptr,3,0,f->flags)) {
else if ( previous_was_break && iscodefence(ptr,3,0,&(f->flags)) ) {
uncache(&source, &d, f);
if ( !fencedcodeblock(&d, &ptr, f->flags) ) /* just source */
if ( !fencedcodeblock(&d, &ptr, &(f->flags)) ) /* just source */
goto attach;
}
else {
@@ -1263,7 +1263,7 @@ actually_a_table(MMIOT *f, Line *pp)
int c;
/* tables need to be turned on */
if ( is_flag_set(f->flags, MKD_NOTABLES) )
if ( is_flag_set(&(f->flags), MKD_NOTABLES) )
return 0;
/* tables need three lines */
@@ -1273,7 +1273,7 @@ actually_a_table(MMIOT *f, Line *pp)
/* all lines must contain |'s */
for (r = pp; r; r = r->next )
if ( !(r->flags & PIPECHAR) ) {
if ( !(r->line_flags & PIPECHAR) ) {
return 0;
}
@@ -1322,7 +1322,7 @@ compile(Line *ptr, int toplevel, MMIOT *f)
if ( iscode(ptr) ) {
p = Pp(&d, ptr, CODE);
if ( is_flag_set(f->flags, MKD_1_COMPAT) ) {
if ( is_flag_set(&(f->flags), MKD_1_COMPAT) ) {
/* HORRIBLE STANDARDS KLUDGE: the first line of every block
* has trailing whitespace trimmed off.
*/
@@ -1331,15 +1331,15 @@ compile(Line *ptr, int toplevel, MMIOT *f)
ptr = codeblock(p);
}
else if ( iscodefence(ptr,3,0,f->flags) && (p=fencedcodeblock(&d, &ptr, f->flags)) )
else if ( iscodefence(ptr,3,0,&(f->flags)) && (p=fencedcodeblock(&d, &ptr, &(f->flags))) )
/* yay, it's already done */ ;
else if ( ishr(ptr, f->flags) ) {
else if ( ishr(ptr, &(f->flags)) ) {
p = Pp(&d, 0, HR);
r = ptr;
ptr = ptr->next;
___mkd_freeLine(r);
}
else if ( list_class = islist(ptr, &indent, f->flags, &list_type) ) {
else if ( list_class = islist(ptr, &indent, &(f->flags), &list_type) ) {
if ( list_class == DL ) {
p = Pp(&d, ptr, DL);
ptr = definition_block(p, indent, f, list_type);
@@ -1351,11 +1351,11 @@ compile(Line *ptr, int toplevel, MMIOT *f)
}
else if ( isquote(ptr) ) {
p = Pp(&d, ptr, QUOTE);
ptr = quoteblock(p, f->flags);
ptr = quoteblock(p, &(f->flags) );
p->down = compile(p->text, 1, f);
p->text = 0;
}
else if ( ishdr(ptr, &hdr_type, f->flags) ) {
else if ( ishdr(ptr, &hdr_type, &(f->flags) ) ) {
p = Pp(&d, ptr, HDR);
ptr = headerblock(p, hdr_type);
}
@@ -1377,7 +1377,7 @@ compile(Line *ptr, int toplevel, MMIOT *f)
* processing with textblock()
*/
if ( !is_flag_set(f->flags, MKD_NOHTML) && (tag = isopentag(ptr)) ) {
if ( !is_flag_set(&(f->flags), MKD_NOHTML) && (tag = isopentag(ptr)) ) {
/* possibly an html block
*/
@@ -1387,7 +1387,7 @@ compile(Line *ptr, int toplevel, MMIOT *f)
}
}
if ( unclosed ) {
ptr = textblock(p, toplevel, f->flags);
ptr = textblock(p, toplevel, &(f->flags) );
/* tables are a special kind of paragraph */
if ( actually_a_table(f, p->text) )
p->typ = TABLE;
@@ -1413,19 +1413,52 @@ compile(Line *ptr, int toplevel, MMIOT *f)
* debugging.
*/
#if DEBUG
static void
sayflags(char *pfx, mkd_flag_t* flags, FILE *output)
{
int i;
fprintf(output, "%.*s/", (int)strlen(pfx), " ");
for (i=0; i<MKD_NR_FLAGS; i++)
fputc( (i==0) || (i % 10) ? ' ' : (i/10)+'0', output);
fputc('\\', output);
fputc('\n', output);
fprintf(output, "%s|", pfx);
for (i=0; i<MKD_NR_FLAGS; i++)
fputc((i%10)+'0', output);
fputc('|', output);
fputc('\n', output);
fprintf(output, "%.*s\\", (int)strlen(pfx), " ");
for (i=0;i<MKD_NR_FLAGS; i++)
fputc(is_flag_set(flags, i)?'X':' ', output);
fputc('/', output);
fputc('\n', output);
}
#else
#define sayflags(pfx,flags,output) 1
#endif
/*
* prepare and compile `text`, returning a Paragraph tree.
*/
int
mkd_compile(Document *doc, mkd_flag_t flags)
mkd_compile(Document *doc, mkd_flag_t* flags)
{
if ( !doc )
return 0;
flags &= USER_FLAGS;
if ( doc->compiled ) {
if ( doc->ctx->flags == flags && !doc->dirty)
mkd_flag_t changed;
if ( flags )
COPY_FLAGS(changed, *flags);
else
mkd_init_flags(&changed);
if ( AND_FLAGS(&changed, &(doc->ctx->flags)) && !doc->dirty )
return 1;
else {
doc->compiled = doc->dirty = 0;
@@ -1440,12 +1473,15 @@ mkd_compile(Document *doc, mkd_flag_t flags)
memset(doc->ctx, 0, sizeof(MMIOT) );
doc->ctx->ref_prefix= doc->ref_prefix;
doc->ctx->cb = &(doc->cb);
doc->ctx->flags = flags;
sayflags("flags", flags, stderr);
COPY_FLAGS(doc->ctx->flags,*flags);
sayflags("used ", &(doc->ctx->flags), stderr);
CREATE(doc->ctx->in);
doc->ctx->footnotes = malloc(sizeof doc->ctx->footnotes[0]);
doc->ctx->footnotes->reference = 0;
CREATE(doc->ctx->footnotes->note);
mkd_initialize();
doc->code = compile_document(T(doc->content), doc->ctx);
+68 -55
View File
@@ -12,11 +12,64 @@
/* flags, captured into a named type
*/
typedef DWORD mkd_flag_t;
enum {
MKD_NOLINKS, /* don't do link processing, block <a> tags */
MKD_NOIMAGE, /* don't do image processing, block <img> */
MKD_NOPANTS, /* don't run smartypants() */
MKD_NOHTML, /* don't allow raw html through AT ALL */
MKD_NORMAL_LISTITEM, /* disable github-style checkbox lists */
MKD_TAGTEXT, /* process text inside an html tag; no <em>, no <bold>,
* no html or [] expansion */
MKD_NO_EXT, /* don't allow pseudo-protocols */
MKD_NOEXT, /* ^^^ (aliased for user convenience) */
MKD_CDATA, /* generate code for xml ![CDATA[...]] */
MKD_NOSUPERSCRIPT, /* no A^B */
MKD_NORELAXED, /* emphasis happens /everywhere/ */
MKD_NOTABLES, /* disallow tables */
MKD_NOSTRIKETHROUGH, /* forbid ~~strikethrough~~ */
MKD_1_COMPAT, /* compatibility with MarkdownTest_1.0 */
MKD_TOC, /* do table-of-contents processing */
MKD_AUTOLINK, /* make http://foo.com link even without <>s */
MKD_NOHEADER, /* don't process header blocks */
MKD_TABSTOP, /* expand tabs to 4 spaces */
MKD_SAFELINK, /* paranoid check for link protocol */
MKD_NODIVQUOTE, /* forbid >%class% blocks */
MKD_NOALPHALIST, /* forbid alphabetic lists */
MKD_EXTRA_FOOTNOTE, /* enable markdown extra-style footnotes */
MKD_NOSTYLE, /* don't extract <style> blocks */
MKD_DLDISCOUNT, /* enable discount-style definition lists */
MKD_DLEXTRA, /* enable extra-style definition lists */
MKD_FENCEDCODE, /* enabled fenced code blocks */
MKD_IDANCHOR, /* use id= anchors for TOC links */
MKD_GITHUBTAGS, /* allow dash and underscore in element names */
MKD_URLENCODEDANCHOR, /* urlencode non-identifier chars instead of replacing with dots */
MKD_LATEX, /* handle embedded LaTeX escapes */
MKD_EXPLICITLIST, /* don't combine numbered/bulletted lists */
/* end of user flags */
IS_LABEL,
MKD_NR_FLAGS };
#define is_flag_set(flags, item) ((flags) & (item))
#define set_flag(flags, item) ((flags) |= (item))
#define clear_flag(flags, item) ((flags) &= ~(item))
typedef struct { char bit[MKD_NR_FLAGS]; } mkd_flag_t;
void ___mkd_or_flags(mkd_flag_t* dst, mkd_flag_t* src);
int ___mkd_and_flags(mkd_flag_t* dst, mkd_flag_t* src);
void mkd_init_flags(mkd_flag_t *p);
#define is_flag_set(flags, item) ((flags)->bit[item])
#define set_mkd_flag(flags, item) ((flags)->bit[item] = 1)
#define clear_mkd_flag(flags, item) ((flags)->bit[item] = 0)
#define COPY_FLAGS(dst,src) memcpy(&dst,&src,sizeof dst)
#define OR_FLAGS(dst,src) ___mkd_or_flags(dst,src)
#define AND_FLAGS(dst,src) ___mkd_and_flags(dst,src)
#define MKD_DLIST MKD_DLDISCOUNT|MKD_DLEXTRA
#define MKD_STRICT MKD_NOSUPERSCRIPT|MKD_NORELAXED|MKD_NOSTRIKETHROUGH| \
MKD_NOHEADER|MKD_NOALPHALIST|MKD_NODIVQUOTE| \
MKD_NOTABLES|MKD_NO_EXT|MKD_NOSTYLE|MKD_NORMAL_LISTITEM| \
MKD_TABSTOP
/* each input line is read into a Line, which contains the line,
* the offset of the first non-space character [this assumes
@@ -31,7 +84,7 @@ typedef struct line {
Cstring text;
struct line *next;
int dle; /* leading indent on the line */
int flags; /* special attributes for this line */
int line_flags; /* special attributes for this line */
#define PIPECHAR 0x01 /* line contains a | */
#define CHECKED 0x02
@@ -55,7 +108,7 @@ typedef struct paragraph {
HDR, HR, TABLE, SOURCE } typ;
enum { IMPLICIT=0, PARA, CENTER} align;
int hnumber; /* <Hn> for typ == HDR */
int flags;
int para_flags;
#define GITHUB_CHECK 0x01
#define IS_CHECKED 0x02
} Paragraph;
@@ -74,7 +127,7 @@ typedef struct footnote {
int height, width; /* dimensions (for image link) */
int dealloc; /* deallocation needed? */
int refnumber;
int flags;
int fn_flags;
#define EXTRA_FOOTNOTE 0x01
#define REFERENCED 0x02
} Footnote;
@@ -129,46 +182,6 @@ typedef struct mmiot {
char *ref_prefix;
struct footnote_list *footnotes;
mkd_flag_t flags;
#define MKD_NOLINKS 0x00000001
#define MKD_NOIMAGE 0x00000002
#define MKD_NOPANTS 0x00000004
#define MKD_NOHTML 0x00000008
#define MKD_NORMAL_LISTITEM 0x00000010
#define MKD_TAGTEXT 0x00000020
#define MKD_NO_EXT 0x00000040
#define MKD_CDATA 0x00000080
#define MKD_NOSUPERSCRIPT 0x00000100
#define MKD_NORELAXED 0x00000200
#define MKD_NOTABLES 0x00000400
#define MKD_NOSTRIKETHROUGH 0x00000800
#define MKD_TOC 0x00001000
#define MKD_1_COMPAT 0x00002000
#define MKD_AUTOLINK 0x00004000
#define MKD_SAFELINK 0x00008000
#define MKD_NOHEADER 0x00010000
#define MKD_TABSTOP 0x00020000
#define MKD_NODIVQUOTE 0x00040000
#define MKD_NOALPHALIST 0x00080000
#define MKD_EXTRA_FOOTNOTE 0x00200000
#define MKD_NOSTYLE 0x00400000
#define MKD_DLDISCOUNT 0x00800000
#define MKD_DLEXTRA 0x01000000
#define MKD_FENCEDCODE 0x02000000
#define MKD_IDANCHOR 0x04000000
#define MKD_GITHUBTAGS 0x08000000
#define MKD_URLENCODEDANCHOR 0x10000000
#define IS_LABEL 0x20000000
#define MKD_LATEX 0x40000000
#define MKD_EXPLICITLIST 0x80000000
#define USER_FLAGS 0xFFFFFFFF
#define INPUT_MASK (MKD_NOHEADER|MKD_TABSTOP)
/* composite flags */
#define MKD_DLIST MKD_DLDISCOUNT|MKD_DLEXTRA
#define MKD_STRICT MKD_NOSUPERSCRIPT|MKD_NORELAXED|MKD_NOSTRIKETHROUGH| \
MKD_NOHEADER|MKD_NOALPHALIST|MKD_NODIVQUOTE| \
MKD_NOTABLES|MKD_NO_EXT|MKD_NOSTYLE|MKD_NORMAL_LISTITEM| \
MKD_TABSTOP
Callback_data *cb;
} MMIOT;
@@ -213,7 +226,7 @@ struct string_stream {
extern int mkd_firstnonblank(Line *);
extern int mkd_compile(Document *, mkd_flag_t);
extern int mkd_compile(Document *, mkd_flag_t*);
extern int mkd_document(Document *, char **);
extern int mkd_generatehtml(Document *, FILE *);
extern int mkd_css(Document *, char **);
@@ -222,19 +235,19 @@ extern int mkd_generatecss(Document *, FILE *);
extern int mkd_xml(char *, int , char **);
extern int mkd_generatexml(char *, int, FILE *);
extern void mkd_cleanup(Document *);
extern int mkd_line(char *, int, char **, mkd_flag_t);
extern int mkd_generateline(char *, int, FILE*, mkd_flag_t);
extern int mkd_line(char *, int, char **, mkd_flag_t*);
extern int mkd_generateline(char *, int, FILE*, mkd_flag_t*);
#define mkd_text mkd_generateline
extern void mkd_basename(Document*, char *);
typedef int (*mkd_sta_function_t)(const int,const void*);
extern void mkd_string_to_anchor(char*,int, mkd_sta_function_t, void*, int, MMIOT *);
extern Document *mkd_in(FILE *, mkd_flag_t);
extern Document *mkd_string(const char*, int, mkd_flag_t);
extern Document *mkd_in(FILE *, mkd_flag_t*);
extern Document *mkd_string(const char*, int, mkd_flag_t*);
extern Document *gfm_in(FILE *, mkd_flag_t);
extern Document *gfm_string(const char*,int, mkd_flag_t);
extern Document *gfm_in(FILE *, mkd_flag_t*);
extern Document *gfm_string(const char*,int, mkd_flag_t*);
extern void mkd_initialize();
extern void mkd_shlib_destructor();
@@ -252,7 +265,7 @@ extern void ___mkd_initmmiot(MMIOT *, void *);
extern void ___mkd_freemmiot(MMIOT *, void *);
extern void ___mkd_freeLineRange(Line *, Line *);
extern void ___mkd_xml(char *, int, FILE *);
extern void ___mkd_reparse(char *, int, mkd_flag_t, MMIOT*, char*);
extern void ___mkd_reparse(char *, int, mkd_flag_t*, MMIOT*, char*);
extern void ___mkd_emblock(MMIOT*);
extern void ___mkd_tidy(Cstring *);
+47 -16
View File
@@ -63,7 +63,7 @@ __mkd_enqueue(Document* a, Cstring *line)
}
else if ( c >= ' ' ) {
if ( c == '|' )
p->flags |= PIPECHAR;
p->line_flags |= PIPECHAR;
EXPAND(p->text) = c;
++xp;
}
@@ -95,7 +95,7 @@ __mkd_trim_line(Line *p, int clip)
typedef int (*getc_func)(void*);
Document *
populate(getc_func getc, void* ctx, mkd_flag_t flags)
populate(getc_func getc, void* ctx, mkd_flag_t *flags)
{
Cstring line;
Document *a = __mkd_new_Document();
@@ -104,6 +104,7 @@ populate(getc_func getc, void* ctx, mkd_flag_t flags)
if ( !a ) return 0;
a->tabstop = is_flag_set(flags, MKD_TABSTOP) ? 4 : TABSTOP;
CREATE(line);
@@ -149,9 +150,9 @@ populate(getc_func getc, void* ctx, mkd_flag_t flags)
/* convert a file into a linked list
*/
Document *
mkd_in(FILE *f, mkd_flag_t flags)
mkd_in(FILE *f, mkd_flag_t *flags)
{
return populate((getc_func)fgetc, f, flags & INPUT_MASK);
return populate((getc_func)fgetc, f, flags);
}
@@ -171,14 +172,14 @@ __mkd_io_strget(struct string_stream *in)
/* convert a block of text into a linked list
*/
Document *
mkd_string(const char *buf, int len, mkd_flag_t flags)
mkd_string(const char *buf, int len, mkd_flag_t* flags)
{
struct string_stream about;
about.data = buf;
about.size = len;
return populate((getc_func)__mkd_io_strget, &about, flags & INPUT_MASK);
return populate((getc_func)__mkd_io_strget, &about, flags);
}
@@ -191,7 +192,7 @@ mkd_generatehtml(Document *p, FILE *output)
int szdoc;
DO_OR_DIE( szdoc = mkd_document(p,&doc) );
if ( is_flag_set(p->ctx->flags, MKD_CDATA) )
if ( is_flag_set( &(p->ctx->flags), MKD_CDATA ) )
DO_OR_DIE( mkd_generatexml(doc, szdoc, output) );
else if ( fwrite(doc, szdoc, 1, output) != 1 )
return EOF;
@@ -203,7 +204,7 @@ mkd_generatehtml(Document *p, FILE *output)
/* convert some markdown text to html
*/
int
markdown(Document *document, FILE *out, mkd_flag_t flags)
markdown(Document *document, FILE *out, mkd_flag_t* flags)
{
if ( mkd_compile(document, flags) ) {
mkd_generatehtml(document, out);
@@ -224,7 +225,7 @@ markdown(Document *document, FILE *out, mkd_flag_t flags)
* labelformat && !h4anchor:expand space to -, other isspace() & '%' to hex
*/
static char *
mkd_anchor_format(char *s, int len, int labelformat, mkd_flag_t flags)
mkd_anchor_format(char *s, int len, int labelformat, mkd_flag_t *flags)
{
char *res;
unsigned char c;
@@ -277,10 +278,13 @@ mkd_string_to_anchor(char *s, int len, mkd_sta_function_t outchar,
char *res;
char *line;
int size;
mkd_flag_t flags;
int i;
size = mkd_line(s, len, &line, IS_LABEL);
mkd_init_flags(&flags);
set_mkd_flag(&flags,IS_LABEL);
size = mkd_line(s, len, &line, &flags);
if ( !line )
return;
@@ -288,7 +292,7 @@ mkd_string_to_anchor(char *s, int len, mkd_sta_function_t outchar,
if ( f->cb->e_anchor )
res = (*(f->cb->e_anchor))(line, size, f->cb->e_data);
else
res = mkd_anchor_format(line, size, labelformat, f->flags);
res = mkd_anchor_format(line, size, labelformat, &(f->flags));
free(line);
@@ -310,11 +314,11 @@ mkd_string_to_anchor(char *s, int len, mkd_sta_function_t outchar,
/* ___mkd_reparse() a line
*/
static void
mkd_parse_line(char *bfr, int size, MMIOT *f, mkd_flag_t flags)
mkd_parse_line(char *bfr, int size, MMIOT *f, mkd_flag_t *flags)
{
___mkd_initmmiot(f, 0);
f->flags = flags & USER_FLAGS;
___mkd_reparse(bfr, size, 0, f, 0);
COPY_FLAGS(f->flags, *flags);
___mkd_reparse(bfr, size, NULL, f, 0);
___mkd_emblock(f);
}
@@ -322,7 +326,7 @@ mkd_parse_line(char *bfr, int size, MMIOT *f, mkd_flag_t flags)
/* ___mkd_reparse() a line, returning it in malloc()ed memory
*/
int
mkd_line(char *bfr, int size, char **res, mkd_flag_t flags)
mkd_line(char *bfr, int size, char **res, mkd_flag_t* flags)
{
MMIOT f;
int len;
@@ -351,7 +355,7 @@ mkd_line(char *bfr, int size, char **res, mkd_flag_t flags)
/* ___mkd_reparse() a line, writing it to a FILE
*/
int
mkd_generateline(char *bfr, int size, FILE *output, mkd_flag_t flags)
mkd_generateline(char *bfr, int size, FILE *output, mkd_flag_t* flags)
{
MMIOT f;
int status;
@@ -455,3 +459,30 @@ mkd_ref_prefix(Document *f, char *data)
f->ref_prefix = data;
}
}
void
___mkd_or_flags(mkd_flag_t *dst, mkd_flag_t *src)
{
int i;
for (i=0; i<MKD_NR_FLAGS; i++)
if ( is_flag_set(src,i) )
set_mkd_flag(dst, i);
}
int
___mkd_and_flags(mkd_flag_t *dst, mkd_flag_t *src)
{
int i;
int count = 0;
for (i=0; i < MKD_NR_FLAGS; i++)
if ( is_flag_set(src,i) && is_flag_set(dst,i) )
++count;
else
clear_mkd_flag(dst, i);
return count;
}
+56 -44
View File
@@ -7,17 +7,27 @@
typedef void MMIOT;
typedef @DWORD@ mkd_flag_t;
typedef struct { char bfr[50]; } mkd_flag_t;
int mkd_flag_isset(mkd_flag_t*, int); /* check a flag status */
void mkd_flag_set(mkd_flag_t*, int); /* set a flag */
void mkd_flag_clear(mkd_flag_t*, int); /* clear a flag */
void mkd_init_flags(mkd_flag_t*); /* initialize the flags */
char *mkd_set_flag_string(mkd_flag_t*, char*); /* set named flags */
void mkd_set_flag_num(mkd_flag_t*, unsigned long);/* set a specific flag */
void mkd_clr_flag_num(mkd_flag_t*, unsigned long);/* clear a specific flag */
void mkd_set_flag_bitmap(mkd_flag_t*,long); /* set a bunch of flags */
/* line builder for markdown()
*/
MMIOT *mkd_in(FILE*,mkd_flag_t); /* assemble input from a file */
MMIOT *mkd_string(const char*,int,mkd_flag_t); /* assemble input from a buffer */
MMIOT *mkd_in(FILE*,mkd_flag_t*); /* assemble input from a file */
MMIOT *mkd_string(const char*,int,mkd_flag_t*); /* assemble input from a buffer */
/* line builder for github flavoured markdown
*/
MMIOT *gfm_in(FILE*,mkd_flag_t); /* assemble input from a file */
MMIOT *gfm_string(const char*,int,mkd_flag_t); /* assemble input from a buffer */
MMIOT *gfm_in(FILE*,mkd_flag_t*); /* assemble input from a file */
MMIOT *gfm_string(const char*,int,mkd_flag_t*); /* assemble input from a buffer */
void mkd_basename(MMIOT*,char*);
@@ -27,15 +37,15 @@ void mkd_shlib_destructor();
/* compilation, debugging, cleanup
*/
int mkd_compile(MMIOT*, mkd_flag_t);
int mkd_compile(MMIOT*, mkd_flag_t*);
void mkd_cleanup(MMIOT*);
/* markup functions
*/
int mkd_dump(MMIOT*, FILE*, mkd_flag_t, char*);
int markdown(MMIOT*, FILE*, mkd_flag_t);
int mkd_line(char *, int, char **, mkd_flag_t);
int mkd_xhtmlpage(MMIOT*,mkd_flag_t,FILE*);
int mkd_dump(MMIOT*, FILE*, mkd_flag_t*, char*);
int markdown(MMIOT*, FILE*, mkd_flag_t*);
int mkd_line(char *, int, char **, mkd_flag_t*);
int mkd_xhtmlpage(MMIOT*,mkd_flag_t*,FILE*);
/* header block access
*/
@@ -57,7 +67,7 @@ int mkd_generatetoc(MMIOT*,FILE*);
int mkd_generatexml(char *, int,FILE*);
int mkd_generatecss(MMIOT*,FILE*);
#define mkd_style mkd_generatecss
int mkd_generateline(char *, int, FILE*, mkd_flag_t);
int mkd_generateline(char *, int, FILE*, mkd_flag_t*);
#define mkd_text mkd_generateline
/* url generator callbacks
@@ -76,45 +86,47 @@ void mkd_e_data(void *, void *);
*/
extern char markdown_version[];
void mkd_mmiot_flags(FILE *, MMIOT *, int);
void mkd_flags_are(FILE*, mkd_flag_t, int);
void mkd_flags_are(FILE*, mkd_flag_t*, int);
void mkd_ref_prefix(MMIOT*, char*);
/* special flags for markdown() and mkd_text()
*/
#define MKD_NOLINKS 0x00000001 /* don't do link processing, block <a> tags */
#define MKD_NOIMAGE 0x00000002 /* don't do image processing, block <img> */
#define MKD_NOPANTS 0x00000004 /* don't run smartypants() */
#define MKD_NOHTML 0x00000008 /* don't allow raw html through AT ALL */
#define MKD_NORMAL_LISTITEM 0x00000010 /* disable github-style checkbox lists */
#define MKD_TAGTEXT 0x00000020 /* process text inside an html tag; no
* <em>, no <bold>, no html or [] expansion */
#define MKD_NO_EXT 0x00000040 /* don't allow pseudo-protocols */
#define MKD_NOEXT MKD_NO_EXT /* ^^^ (aliased for user convenience) */
#define MKD_CDATA 0x00000080 /* generate code for xml ![CDATA[...]] */
#define MKD_NOSUPERSCRIPT 0x00000100 /* no A^B */
#define MKD_NORELAXED 0x00000200 /* emphasis happens /everywhere/ */
#define MKD_NOTABLES 0x00000400 /* disallow tables */
#define MKD_NOSTRIKETHROUGH 0x00000800 /* forbid ~~strikethrough~~ */
#define MKD_TOC 0x00001000 /* do table-of-contents processing */
#define MKD_1_COMPAT 0x00002000 /* compatibility with MarkdownTest_1.0 */
#define MKD_AUTOLINK 0x00004000 /* make http://foo.com link even without <>s */
#define MKD_SAFELINK 0x00008000 /* paranoid check for link protocol */
#define MKD_NOHEADER 0x00010000 /* don't process header blocks */
#define MKD_TABSTOP 0x00020000 /* expand tabs to 4 spaces */
#define MKD_NODIVQUOTE 0x00040000 /* forbid >%class% blocks */
#define MKD_NOALPHALIST 0x00080000 /* forbid alphabetic lists */
#define MKD_EXTRA_FOOTNOTE 0x00200000 /* enable markdown extra-style footnotes */
#define MKD_NOSTYLE 0x00400000 /* don't extract <style> blocks */
#define MKD_DLDISCOUNT 0x00800000 /* enable discount-style definition lists */
#define MKD_DLEXTRA 0x01000000 /* enable extra-style definition lists */
#define MKD_FENCEDCODE 0x02000000 /* enabled fenced code blocks */
#define MKD_IDANCHOR 0x04000000 /* use id= anchors for TOC links */
#define MKD_GITHUBTAGS 0x08000000 /* allow dash and underscore in element names */
#define MKD_URLENCODEDANCHOR 0x10000000 /* urlencode non-identifier chars instead of replacing with dots */
#define MKD_LATEX 0x40000000 /* handle embedded LaTeX escapes */
#define MKD_EXPLICITLIST 0x80000000 /* don't combine numbered/bulletted lists */
enum {
MKD_NOLINKS, /* don't do link processing, block <a> tags */
MKD_NOIMAGE, /* don't do image processing, block <img> */
MKD_NOPANTS, /* don't run smartypants() */
MKD_NOHTML, /* don't allow raw html through AT ALL */
MKD_NORMAL_LISTITEM, /* disable github-style checkbox lists */
MKD_TAGTEXT, /* process text inside an html tag; no <em>, no <bold>,
* no html or [] expansion */
MKD_NO_EXT, /* don't allow pseudo-protocols */
MKD_NOEXT, /* ^^^ (aliased for user convenience) */
MKD_CDATA, /* generate code for xml ![CDATA[...]] */
MKD_NOSUPERSCRIPT, /* no A^B */
MKD_NORELAXED, /* emphasis happens /everywhere/ */
MKD_NOTABLES, /* disallow tables */
MKD_NOSTRIKETHROUGH, /* forbid ~~strikethrough~~ */
MKD_1_COMPAT, /* compatibility with MarkdownTest_1.0 */
MKD_TOC, /* do table-of-contents processing */
MKD_AUTOLINK, /* make http://foo.com link even without <>s */
MKD_TABSTOP, /* expand tabs to 4 spaces */
MKD_NOHEADER, /* don't process header blocks */
MKD_SAFELINK, /* paranoid check for link protocol */
MKD_NODIVQUOTE, /* forbid >%class% blocks */
MKD_NOALPHALIST, /* forbid alphabetic lists */
MKD_EXTRA_FOOTNOTE, /* enable markdown extra-style footnotes */
MKD_NOSTYLE, /* don't extract <style> blocks */
MKD_DLDISCOUNT, /* enable discount-style definition lists */
MKD_DLEXTRA, /* enable extra-style definition lists */
MKD_FENCEDCODE, /* enabled fenced code blocks */
MKD_IDANCHOR, /* use id= anchors for TOC links */
MKD_GITHUBTAGS, /* allow dash and underscore in element names */
MKD_URLENCODEDANCHOR, /* urlencode non-identifier chars instead of replacing with dots */
MKD_LATEX, /* handle embedded LaTeX escapes */
MKD_EXPLICITLIST, /* don't combine numbered/bulletted lists */
MKD_NR_FLAGS };
#define MKD_EMBED MKD_NOLINKS|MKD_NOIMAGE|MKD_TAGTEXT
#define MKD_DLIST MKD_DLDISCOUNT|MKD_DLEXTRA
+151 -40
View File
@@ -8,67 +8,78 @@
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <mkdio.h>
#include <errno.h>
#include <string.h>
#include <stdarg.h>
#include "config.h"
#include "markdown.h"
#include "amalloc.h"
#if HAVE_LIBGEN_H
#include <libgen.h>
#endif
static void set_dlist(mkd_flag_t *, int);
static void set_standard(mkd_flag_t *, int);
static struct _special {
char *name;
void (*setter)(mkd_flag_t *, int);
} special[] = {
{ "definitionlist", set_dlist },
{ "dlist", set_dlist },
{ "standard", set_standard },
};
static struct _opt {
char *name;
char *desc;
int special;
int off;
int skip; /* this opt is a synonym; don't display in -F? */
int composite; /* composite flag; don't display in -F? */
int alias; /* this opt is a synonym; don't display in -F? */
int sayenable;
mkd_flag_t flag; /* flags to set/clear */
mkd_flag_t unflag; /* flags to clear/set */
int flag; /* flag to set/clear */
int unflag; /* flag to clear/set */
} opts[] = {
{ "tabstop", "default (4-space) tabstops", 0, 0, 0, 1, MKD_TABSTOP },
{ "image", "images", 1, 0, 0, 1, MKD_NOIMAGE },
{ "links", "links", 1, 0, 0, 1, MKD_NOLINKS },
{ "image", "images", 0, 1, 0, 1, MKD_NOIMAGE },
{ "links", "links", 0, 1, 0, 1, MKD_NOLINKS },
{ "strict", "emphasis inside words", 0, 0, 0, 1, MKD_NORELAXED },
{ "relax", "emphasis inside words", 1, 1, 0, 1, MKD_NORELAXED },
{ "tables", "tables", 1, 0, 0, 1, MKD_NOTABLES },
{ "header", "pandoc-style headers", 1, 0, 0, 1, MKD_NOHEADER },
{ "html", "allow raw html", 1, 0, 0, 0, MKD_NOHTML },
{ "ext", "extended protocols", 1, 0, 0, 1, MKD_NO_EXT },
{ "relax", "emphasis inside words", 0, 1, 1, 1, MKD_NORELAXED },
{ "tables", "tables", 0, 1, 0, 1, MKD_NOTABLES },
{ "header", "pandoc-style headers", 0, 1, 0, 1, MKD_NOHEADER },
{ "html", "allow raw html", 0, 1, 0, 0, MKD_NOHTML },
{ "ext", "extended protocols", 0, 1, 0, 1, MKD_NO_EXT },
{ "cdata", "generate cdata", 0, 0, 0, 0, MKD_CDATA },
{ "smarty", "smartypants", 1, 0, 0, 1, MKD_NOPANTS },
{ "pants", "smartypants", 1, 1, 0, 1, MKD_NOPANTS },
{ "smarty", "smartypants", 0, 1, 0, 1, MKD_NOPANTS },
{ "pants", "smartypants", 0, 1, 1, 1, MKD_NOPANTS },
{ "toc", "tables of contents", 0, 0, 0, 1, MKD_TOC },
{ "autolink", "autolinking", 0, 0, 0, 1, MKD_AUTOLINK },
{ "safelink", "safe links", 0, 0, 0, 1, MKD_SAFELINK },
{ "strikethrough", "strikethrough", 1, 0, 0, 1, MKD_NOSTRIKETHROUGH },
{ "del", "strikethrough", 1, 1, 0, 1, MKD_NOSTRIKETHROUGH },
{ "superscript", "superscript", 1, 0, 0, 1, MKD_NOSUPERSCRIPT },
{ "divquote", ">%class% blockquotes", 1, 0, 0, 1, MKD_NODIVQUOTE },
{ "alphalist", "alpha lists", 1, 0, 0, 1, MKD_NOALPHALIST },
{ "definitionlist","both discount & markdown extra definition lists", 0, 0, 1, 1, MKD_DLIST },
{ "dlist", "both discount & markdown extra definition lists", 0, 1, 1, 1, MKD_DLIST },
{ "strikethrough", "strikethrough", 0, 1, 0, 1, MKD_NOSTRIKETHROUGH },
{ "del", "strikethrough", 0, 1, 1, 1, MKD_NOSTRIKETHROUGH },
{ "superscript", "superscript", 0, 1, 0, 1, MKD_NOSUPERSCRIPT },
{ "divquote", ">%class% blockquotes", 0, 1, 0, 1, MKD_NODIVQUOTE },
{ "alphalist", "alpha lists", 0, 1, 0, 1, MKD_NOALPHALIST },
{ "1.0", "markdown 1.0 compatibility", 0, 0, 0, 1, MKD_1_COMPAT },
{ "footnotes", "markdown extra footnotes", 0, 0, 0, 1, MKD_EXTRA_FOOTNOTE },
{ "footnote", "markdown extra footnotes", 0, 1, 0, 1, MKD_EXTRA_FOOTNOTE },
{ "style", "extract style blocks", 1, 0, 0, 1, MKD_NOSTYLE },
{ "footnote", "markdown extra footnotes", 0, 0, 1, 1, MKD_EXTRA_FOOTNOTE },
{ "style", "extract style blocks", 0, 1, 0, 1, MKD_NOSTYLE },
{ "dldiscount", "discount-style definition lists", 0, 0, 0, 1, MKD_DLDISCOUNT },
{ "dlextra", "markdown extra-style definition lists", 0, 0, 0, 1, MKD_DLEXTRA },
{ "fencedcode", "fenced code blocks", 0, 0, 0, 1, MKD_FENCEDCODE },
{ "idanchor", "id= anchors in TOC", 0, 0, 0, 1, MKD_IDANCHOR },
{ "githubtags", "- and _ in element names", 0, 0, 0, 1, MKD_GITHUBTAGS },
{ "urlencodedanchor", "html5-style anchors", 0, 0, 0, 1, MKD_URLENCODEDANCHOR },
{ "html5anchor", "html5-style anchors", 0, 1, 0, 1, MKD_URLENCODEDANCHOR },
{ "html5anchor", "html5-style anchors", 0, 0, 1, 1, MKD_URLENCODEDANCHOR },
{ "latex", "LaTeX escapes", 0, 0, 0, 1, MKD_LATEX },
{ "explicitlist", "merge adjacent numeric/bullet lists", 0, 0, 0, 0, MKD_EXPLICITLIST },
{ "github-listitem","github-style check items", 1, 0, 0, 1, MKD_NORMAL_LISTITEM } ,
{ "regular-listitem","github-style check items", 0, 1, 0, 1, MKD_NORMAL_LISTITEM } ,
{ "standard", "conform to the markdown standard", 0, 0, 1, 0, MKD_STRICT,
MKD_FENCEDCODE|MKD_LATEX|MKD_TABSTOP|MKD_EXTRA_FOOTNOTE|MKD_AUTOLINK|MKD_SAFELINK|MKD_TOC|MKD_DLIST },
{ "github-listitem","github-style check items", 0, 1, 0, 1, MKD_NORMAL_LISTITEM } ,
{ "regular-listitem","github-style check items", 0, 0, 1, 1, MKD_NORMAL_LISTITEM } ,
{ "definitionlist","both discount & markdown extra definition lists", 1 },
{ "dlist", "both discount & markdown extra definition lists", 1, 0, 1 },
{ "standard", "conform to the markdown standard", 1 },
} ;
#define NR(x) (sizeof x / sizeof x[0])
@@ -90,38 +101,103 @@ sort_by_flag(struct _opt *a, struct _opt *b)
void
show_flags(int byname, int verbose)
show_flags(int byname, int verbose, mkd_flag_t *flags)
{
int i;
if ( byname ) {
qsort(opts, NR(opts), sizeof(opts[0]), (stfu)sort_by_name);
for (i=0; i < NR(opts); i++)
if ( verbose || !opts[i].skip )
for (i=0; i < NR(opts); i++) {
if ( opts[i].special || (opts[i].alias && !verbose) )
continue;
if ( (flags==0) || is_flag_set(flags, opts[i].flag) )
fprintf(stderr, "%16s : %s\n", opts[i].name, opts[i].desc);
}
}
else {
qsort(opts, NR(opts), sizeof(opts[0]), (stfu)sort_by_flag);
for (i=0; i < NR(opts); i++)
if ( !(opts[i].skip || opts[i].composite) ) {
fprintf(stderr, "%08lx : ", (long)opts[i].flag);
for (i=0; i < NR(opts) && i < 8*sizeof(DWORD); i++) {
if ( opts[i].special || opts[i].alias )
continue;
if ( (flags==0) || is_flag_set(flags, opts[i].flag) ) {
fprintf(stderr, "%08lx : ", 1L<<opts[i].flag);
if ( opts[i].sayenable )
fprintf(stderr, opts[i].off ? "disable " : "enable ");
fprintf(stderr, "%s\n", opts[i].desc);
}
}
}
}
static void
set_dlist(mkd_flag_t *flags, int enable)
{
if ( enable ) {
set_mkd_flag(flags, MKD_DLDISCOUNT);
set_mkd_flag(flags, MKD_DLEXTRA);
}
else {
clear_mkd_flag(flags, MKD_DLDISCOUNT);
clear_mkd_flag(flags, MKD_DLEXTRA);
}
}
static void
set_standard(mkd_flag_t *flags, int enable)
{
if ( enable ) {
clear_mkd_flag(flags, MKD_FENCEDCODE);
clear_mkd_flag(flags, MKD_LATEX);
clear_mkd_flag(flags, MKD_TABSTOP);
clear_mkd_flag(flags, MKD_EXTRA_FOOTNOTE);
clear_mkd_flag(flags, MKD_AUTOLINK);
clear_mkd_flag(flags, MKD_SAFELINK);
clear_mkd_flag(flags, MKD_TOC);
clear_mkd_flag(flags, MKD_DLDISCOUNT);
clear_mkd_flag(flags, MKD_DLEXTRA);
set_mkd_flag(flags, MKD_NOSUPERSCRIPT);
set_mkd_flag(flags, MKD_NORMAL_LISTITEM);
set_mkd_flag(flags, MKD_NO_EXT);
set_mkd_flag(flags, MKD_NOEXT);
set_mkd_flag(flags, MKD_NOSUPERSCRIPT);
set_mkd_flag(flags, MKD_NORELAXED);
set_mkd_flag(flags, MKD_NOTABLES);
set_mkd_flag(flags, MKD_NOSTRIKETHROUGH);
set_mkd_flag(flags, MKD_NOHEADER);
set_mkd_flag(flags, MKD_NODIVQUOTE);
set_mkd_flag(flags, MKD_NOALPHALIST);
set_mkd_flag(flags, MKD_NOSTYLE);
}
}
static void
handle_special(mkd_flag_t *flags, char *opt, int enable)
{
int i;
for (i=0; i < NR(special); i++)
if ( strcasecmp(opt, special[i].name) == 0 ) {
(special[i].setter)(flags, enable);
return;
}
}
char *
set_flag(mkd_flag_t *flags, char *optionstring)
mkd_set_flag_string(mkd_flag_t *flags, char *optionstring)
{
int i;
int enable;
char *arg;
if ( flags == 0 ) /* shouldn't happen */
return "NULL";
for ( arg = strtok(optionstring, ","); arg; arg = strtok(NULL, ",") ) {
if ( *arg == '+' || *arg == '-' )
enable = (*arg++ == '+') ? 1 : 0;
@@ -137,18 +213,23 @@ set_flag(mkd_flag_t *flags, char *optionstring)
break;
if ( i < NR(opts) ) {
if ( opts[i].special ) {
handle_special(flags, opts[i].name, enable);
continue;
}
if ( opts[i].off )
enable = !enable;
if ( enable ) {
*flags |= opts[i].flag;
set_mkd_flag(flags, opts[i].flag);
if ( opts[i].unflag )
*flags &= ~opts[i].unflag;
clear_mkd_flag(flags, opts[i].unflag);
}
else {
*flags &= ~opts[i].flag;
clear_mkd_flag(flags, opts[i].flag);
if ( opts[i].unflag )
*flags |= opts[i].unflag;
set_mkd_flag(flags, opts[i].unflag);
}
}
else
@@ -156,3 +237,33 @@ set_flag(mkd_flag_t *flags, char *optionstring)
}
return 0;
}
void
mkd_set_flag_num(mkd_flag_t *p, unsigned long bit)
{
if ( p && (bit < MKD_NR_FLAGS) )
set_mkd_flag(p, bit);
}
void
mkd_clr_flag_num(mkd_flag_t *p, unsigned long bit)
{
if ( p && (bit < MKD_NR_FLAGS) )
clear_mkd_flag(p, bit);
}
void
mkd_set_flag_bitmap(mkd_flag_t *p, long bits)
{
int i;
if ( p == 0 )
return;
for (i=0; i < 8*sizeof(long) && i < MKD_NR_FLAGS; i++)
if ( bits & (1<<i) )
set_mkd_flag(p, i);
}
+1 -2
View File
@@ -3,7 +3,6 @@
#include <mkdio.h>
char *set_flag(mkd_flag_t *flags, char *optionstring);
void show_flags(int byname, int verbose);
void show_flags(int byname, int verbose, mkd_flag_t *flags);
#endif/*PGM_OPTIONS_D*/
+2 -2
View File
@@ -10,13 +10,13 @@ try -flatex 'latex w/ \( .. \) and link inside' '\([(1+2)*3-4](1-2)\)' '<p>\([(1
try -flatex 'latex w/ \( .. \) and special characters' 'Equation:\(a<+>b\).' \
'<p>Equation:\(a&lt;+&gt;b\).</p>'
try -flatex 'latex $ delimiter not supported' '$[a](b)$' '<p>$<a href="b">a</a>$</p>'
#try -flatex 'latex $ delimiter not supported' '$[a](b)$' '<p>$<a href="b">a</a>$</p>'
try -flatex 'latex with $$ .. $$' '$$foo$$' '<p>$$foo$$</p>'
try -flatex 'latex with $$ .. $$ like a link' '$$[(1+2)*3-4](1-2)$$' '<p>$$[(1+2)*3-4](1-2)$$</p>'
try -flatex 'latex with multiple $$ .. $$' '$$[a](b)$$$$[a](b)$$' '<p>$$[a](b)$$$$[a](b)$$</p>'
try -flatex 'latex with $$ .. $$ and a real link' '$$[a](b)$$[a](b)$$' '<p>$$[a](b)$$<a href="b">a</a>$$</p>'
try -flatex 'latex with $$ .. $$ and a real link' '$$[a](b)$$$[a](b)$$' '<p>$$[a](b)$$$<a href="b">a</a>$$</p>'
#try -flatex 'latex with $$ .. $$ and a real link' '$$[a](b)$$$[a](b)$$' '<p>$$[a](b)$$$<a href="b">a</a>$$</p>'
try -flatex 'latex with $$ .. $$ multi lines' '$$\begin{split}\nabla \times \vec{\mathbf{B}} -\, \frac1c\, \frac{\partial\vec{\mathbf{E}}}{\partial t} & = \frac{4\pi}{c}\vec{\mathbf{j}} \\ \nabla \cdot \vec{\mathbf{E}} & = 4 \pi \rho \\ \nabla \times \vec{\mathbf{E}}\, +\, \frac1c\, \frac{\partial\vec{\mathbf{B}}}{\partial t} & = \vec{\mathbf{0}} \\ \nabla \cdot \vec{\mathbf{B}} & = 0 \end{split}$$' '<p>$$\begin{split}\nabla \times \vec{\mathbf{B}} -\, \frac1c\, \frac{\partial\vec{\mathbf{E}}}{\partial t} &amp; = \frac{4\pi}{c}\vec{\mathbf{j}} \\ \nabla \cdot \vec{\mathbf{E}} &amp; = 4 \pi \rho \\ \nabla \times \vec{\mathbf{E}}\, +\, \frac1c\, \frac{\partial\vec{\mathbf{B}}}{\partial t} &amp; = \vec{\mathbf{0}} \\ \nabla \cdot \vec{\mathbf{B}} &amp; = 0 \end{split}$$</p>'
try -flatex 'latex with \[ .. \]' '\[foo\]' '<p>\[foo\]</p>'
+35 -35
View File
@@ -256,7 +256,7 @@ istag(int *p, char *pat)
/* finclude() includes some (unformatted) source
*/
static void
finclude(MMIOT *doc, FILE *out, int flags, int whence)
finclude(MMIOT *doc, FILE *out, mkd_flag_t *flags, int whence)
{
int c;
Cstring include;
@@ -287,7 +287,7 @@ finclude(MMIOT *doc, FILE *out, int flags, int whence)
/* fdirname() prints out the directory part of a path
*/
static void
fdirname(MMIOT *doc, FILE *output, int flags, int whence)
fdirname(MMIOT *doc, FILE *output, mkd_flag_t *flags, int whence)
{
char *p;
@@ -299,7 +299,7 @@ fdirname(MMIOT *doc, FILE *output, int flags, int whence)
/* fbasename() prints out the file name part of a path
*/
static void
fbasename(MMIOT *doc, FILE *output, int flags, int whence)
fbasename(MMIOT *doc, FILE *output, mkd_flag_t *flags, int whence)
{
char *p;
@@ -318,7 +318,7 @@ fbasename(MMIOT *doc, FILE *output, int flags, int whence)
/* ftitle() prints out the document title
*/
static void
ftitle(MMIOT *doc, FILE* output, int flags, int whence)
ftitle(MMIOT *doc, FILE* output, mkd_flag_t *flags, int whence)
{
char *h;
h = mkd_doc_title(doc);
@@ -339,19 +339,22 @@ ftitle(MMIOT *doc, FILE* output, int flags, int whence)
/* fdate() prints out the document date
*/
static void
fdate(MMIOT *doc, FILE *output, int flags, int whence)
fdate(MMIOT *doc, FILE *output, mkd_flag_t *flags, int whence)
{
char *h;
if ( (h = mkd_doc_date(doc)) || ( infop && (h = ctime(&infop->st_mtime)) ) )
mkd_generateline(h, strlen(h), output, flags|MKD_TAGTEXT);
if ( (h = mkd_doc_date(doc)) || ( infop && (h = ctime(&infop->st_mtime)) ) ) {
mkd_set_flag_num(flags, MKD_TAGTEXT);
mkd_generateline(h, strlen(h), output, flags);
mkd_clr_flag_num(flags, MKD_TAGTEXT);
}
}
/* fauthor() prints out the document author
*/
static void
fauthor(MMIOT *doc, FILE *output, int flags, int whence)
fauthor(MMIOT *doc, FILE *output, mkd_flag_t *flags, int whence)
{
char *h = mkd_doc_author(doc);
@@ -369,7 +372,7 @@ fauthor(MMIOT *doc, FILE *output, int flags, int whence)
* tabular versions of the flags.
*/
static void
fconfig(MMIOT *doc, FILE *output, int flags, int whence)
fconfig(MMIOT *doc, FILE *output, mkd_flag_t *flags, int whence)
{
mkd_mmiot_flags(output, doc, (whence & (INHEAD|INTAG)) ? 0 : 1);
}
@@ -378,7 +381,7 @@ fconfig(MMIOT *doc, FILE *output, int flags, int whence)
/* fversion() prints out the document version
*/
static void
fversion(MMIOT *doc, FILE *output, int flags, int whence)
fversion(MMIOT *doc, FILE *output, mkd_flag_t *flags, int whence)
{
fwrite(markdown_version, strlen(markdown_version), 1, output);
}
@@ -387,7 +390,7 @@ fversion(MMIOT *doc, FILE *output, int flags, int whence)
/* fbody() prints out the document
*/
static void
fbody(MMIOT *doc, FILE *output, int flags, int whence)
fbody(MMIOT *doc, FILE *output, mkd_flag_t *flags, int whence)
{
mkd_generatehtml(doc, output);
}
@@ -395,7 +398,7 @@ fbody(MMIOT *doc, FILE *output, int flags, int whence)
/* ftoc() prints out the table of contents
*/
static void
ftoc(MMIOT *doc, FILE *output, int flags, int whence)
ftoc(MMIOT *doc, FILE *output, mkd_flag_t *flags, int whence)
{
mkd_generatetoc(doc, output);
}
@@ -403,7 +406,7 @@ ftoc(MMIOT *doc, FILE *output, int flags, int whence)
/* fstyle() prints out the document's style section
*/
static void
fstyle(MMIOT *doc, FILE *output, int flags, int whence)
fstyle(MMIOT *doc, FILE *output, mkd_flag_t *flags, int whence)
{
mkd_generatecss(doc, output);
}
@@ -425,7 +428,7 @@ fstyle(MMIOT *doc, FILE *output, int flags, int whence)
static struct _keyword {
char *kw;
int where;
void (*what)(MMIOT*,FILE*,int,int);
void (*what)(MMIOT*,FILE*,mkd_flag_t *,int);
} keyword[] = {
{ "author?>", 0xffff, fauthor },
{ "body?>", INBODY, fbody },
@@ -449,7 +452,7 @@ spin(FILE *template, MMIOT *doc, FILE *output)
{
int c;
int *p;
int flags;
mkd_flag_t flags;
int where = 0x0;
int i;
@@ -473,17 +476,21 @@ spin(FILE *template, MMIOT *doc, FILE *output)
shift(-1);
p = cursor();
if ( where & INTAG )
flags = MKD_TAGTEXT;
else if ( where & INHEAD )
flags = MKD_NOIMAGE|MKD_NOLINKS;
else
flags = 0;
for (i=0; i < NR(keyword); i++)
if ( thesame(p, keyword[i].kw) ) {
if ( everywhere || (keyword[i].where & where) )
(*keyword[i].what)(doc,output,flags,where);
if ( everywhere || (keyword[i].where & where) ) {
mkd_init_flags(&flags);
mkd_set_flag_num(&flags, THEME_CF);
mkd_set_flag_num(&flags, MKD_TOC);
if ( where & INTAG )
mkd_set_flag_num(&flags, MKD_TAGTEXT);
else if ( where & INHEAD ) {
mkd_set_flag_num(&flags, MKD_NOIMAGE);
mkd_set_flag_num(&flags, MKD_NOLINKS);
}
(*keyword[i].what)(doc,output,&flags,where);
}
break;
}
@@ -533,7 +540,7 @@ char **argv;
char *template = "page.theme";
char *source = "stdin";
FILE *tmplfile;
mkd_flag_t flags = THEME_CF|MKD_TOC;
mkd_flag_t flags;
int force = 0;
MMIOT *doc;
struct stat sourceinfo;
@@ -563,18 +570,11 @@ char **argv;
break;
case 't': template = hoptarg(&blob);
break;
case 'C': if ( strcmp(hoptarg(&blob), "?") == 0 ) {
show_flags(0,0);
exit(0);
}
else
flags = strtol(hoptarg(&blob), 0, 0);
break;
case 'c': if ( strcmp(hoptarg(&blob), "?") == 0 ) {
show_flags(1,0);
show_flags(1,0, 0);
exit(0);
}
else if ( q = set_flag(&flags, hoptarg(&blob)) )
else if ( q = mkd_set_flag_string(&flags, hoptarg(&blob)) )
fprintf(stderr,"%s: unknown option <%s>", pgm, q);
break;
case 'o': output_file = hoptarg(&blob);
@@ -653,7 +653,7 @@ char **argv;
fail("out of memory");
#endif
if ( !mkd_compile(doc, flags) )
if ( !mkd_compile(doc, &flags) )
fail("couldn't compile input");
if ( tmplfile )
+13 -3
View File
@@ -15,6 +15,9 @@
#include "markdown.h"
#include "amalloc.h"
/* inport from Csio.c */
extern void Csreparse(Cstring *, char *, int, mkd_flag_t*);
/* write an header index
*/
int
@@ -25,14 +28,21 @@ mkd_toc(Document *p, char **doc)
Cstring res;
int size;
int first = 1;
extern void Csreparse(Cstring *, char *, int, mkd_flag_t);
#if 0
static mkd_flag_t islabel = { { [IS_LABEL] = 1 } };
#else
mkd_flag_t islabel;
mkd_init_flags(&islabel);
#endif
set_mkd_flag(&islabel, IS_LABEL);
if ( !(doc && p && p->ctx) ) return -1;
*doc = 0;
if ( ! is_flag_set(p->ctx->flags, MKD_TOC) ) return 0;
if ( ! is_flag_set(&p->ctx->flags, MKD_TOC) ) return 0;
CREATE(res);
RESERVE(res, 100);
@@ -68,7 +78,7 @@ mkd_toc(Document *p, char **doc)
&res,1,p->ctx);
Csprintf(&res, "\">");
Csreparse(&res, T(srcp->text->text),
S(srcp->text->text), IS_LABEL);
S(srcp->text->text), &islabel);
Csprintf(&res, "</a>");
first = 0;
+1 -1
View File
@@ -11,7 +11,7 @@
int
mkd_xhtmlpage(Document *p, mkd_flag_t flags, FILE *out)
mkd_xhtmlpage(Document *p, mkd_flag_t* flags, FILE *out)
{
char *title;
extern char *mkd_doc_title(Document *);