diff --git a/Makefile.in b/Makefile.in index 53ec5e2..18d6db3 100644 --- a/Makefile.in +++ b/Makefile.in @@ -65,6 +65,11 @@ $(DESTDIR)/$(LIBDIR): version.o: version.c VERSION $(CC) -DVERSION=\"`cat VERSION`\" -c version.c +tags.o: tags.c blocktags + +blocktags: mktags + ./mktags > blocktags + # example programs @THEME@theme: theme.o $(MKDLIB) mkdio.h @THEME@ $(CC) -o theme theme.o -lmarkdown @LIBS@ diff --git a/VERSION b/VERSION index dfe6819..b675cc1 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.1.1.1 +2.1.1.2 diff --git a/html5.c b/html5.c index 8b86988..de91b90 100644 --- a/html5.c +++ b/html5.c @@ -10,8 +10,6 @@ mkd_with_html5_tags() if ( populated ) return; populated = 1; - mkd_prepare_tags(); - mkd_define_tag("ASIDE", 0); mkd_define_tag("FOOTER", 0); mkd_define_tag("HEADER", 0); diff --git a/mktags.c b/mktags.c new file mode 100644 index 0000000..daffefe --- /dev/null +++ b/mktags.c @@ -0,0 +1,108 @@ +/* block-level tags for passing html blocks through the blender + */ +#include + +#define __WITHOUT_AMALLOC 1 +#include "cstring.h" +#include "tags.h" + +STRING(struct kw) blocktags; + + +/* define a html block tag + */ +void +mkd_define_tag(char *id, int selfclose) +{ + struct kw *p = &EXPAND(blocktags); + + p->id = id; + p->size = strlen(id); + p->selfclose = selfclose; +} + + +/* case insensitive string sort (for qsort() and bsearch() of block tags) + */ +static int +casort(struct kw *a, struct kw *b) +{ + if ( a->size != b->size ) + return a->size - b->size; + return strncasecmp(a->id, b->id, b->size); +} + + +/* stupid cast to make gcc shut up about the function types being + * passed into qsort() and bsearch() + */ +typedef int (*stfu)(const void*,const void*); + + +/* sort the list of html block tags for later searching + */ +void +mkd_sort_tags() +{ + qsort(T(blocktags), S(blocktags), sizeof(struct kw), (stfu)casort); +} + + + +/* load in the standard collection of html tags that markdown supports + */ +static void +pile_of_tags() +{ + +#define KW(x) mkd_define_tag(x, 0) +#define SC(x) mkd_define_tag(x, 1) + + KW("STYLE"); + KW("SCRIPT"); + KW("ADDRESS"); + KW("BDO"); + KW("BLOCKQUOTE"); + KW("CENTER"); + KW("DFN"); + KW("DIV"); + KW("OBJECT"); + KW("H1"); + KW("H2"); + KW("H3"); + KW("H4"); + KW("H5"); + KW("H6"); + KW("LISTING"); + KW("NOBR"); + KW("UL"); + KW("P"); + KW("OL"); + KW("DL"); + KW("PLAINTEXT"); + KW("PRE"); + KW("TABLE"); + KW("WBR"); + KW("XMP"); + SC("HR"); + SC("BR"); + KW("IFRAME"); + KW("MAP"); + + mkd_sort_tags(); +} /* pile_of_tags */ + + +main() +{ + + int i; + pile_of_tags(); + + printf("struct kw blocktags[] = {\n"); + for (i=0; i < S(blocktags); i++) + printf(" { \"%s\", %d, %d },\n", T(blocktags)[i].id, T(blocktags)[i].size, T(blocktags)[i].selfclose ); + printf("};\n\n"); + printf("#define NR_blocktags %d\n", S(blocktags)); + exit(0); +} diff --git a/setup.c b/setup.c index 79f47aa..988a6aa 100644 --- a/setup.c +++ b/setup.c @@ -18,7 +18,6 @@ #include "amalloc.h" #include "tags.h" -static int need_to_setup = 1; static int need_to_initrng = 1; void @@ -29,19 +28,12 @@ mkd_initialize() need_to_initrng = 0; INITRNG(time(0)); } - if ( need_to_setup ) { - need_to_setup = 0; - mkd_prepare_tags(); - } } void mkd_shlib_destructor() { - if ( !need_to_setup ) { - need_to_setup = 1; - mkd_deallocate_tags(); - } + mkd_deallocate_tags(); } diff --git a/tags.c b/tags.c index 00affc1..b5043dd 100644 --- a/tags.c +++ b/tags.c @@ -4,19 +4,33 @@ #include "cstring.h" #include "tags.h" -STRING(struct kw) blocktags; +STRING(struct kw) extratags; + +/* the standard collection of tags are built and sorted when + * discount is configured, so all we need to do is pull them + * in and use them. + * + * Additional tags still need to be allocated, sorted, and deallocated. + */ +#include "blocktags" -/* define a html block tag +/* define an additional html block tag */ void mkd_define_tag(char *id, int selfclose) { - struct kw *p = &EXPAND(blocktags); + struct kw *p; - p->id = id; - p->size = strlen(id); - p->selfclose = selfclose; + /* only add the new tag if it doesn't exist in + * either the standard or extra tag tables. + */ + if ( !(p = mkd_search_tags(id, strlen(id))) ) { + p = &EXPAND(extratags); + p->id = id; + p->size = strlen(id); + p->selfclose = selfclose; + } } @@ -37,87 +51,41 @@ casort(struct kw *a, struct kw *b) typedef int (*stfu)(const void*,const void*); -/* sort the list of html block tags for later searching +/* sort the list of extra html block tags for later searching */ void mkd_sort_tags() { - qsort(T(blocktags), S(blocktags), sizeof(struct kw), (stfu)casort); + qsort(T(extratags), S(extratags), sizeof(struct kw), (stfu)casort); } - /* look for a token in the html block tag list */ struct kw* mkd_search_tags(char *pat, int len) { struct kw key; + struct kw *ret; key.id = pat; key.size = len; - return bsearch(&key, T(blocktags), S(blocktags), sizeof key, (stfu)casort); + if ( (ret=bsearch(&key,blocktags,NR_blocktags,sizeof key,(stfu)casort)) ) + return ret; + + if ( S(extratags) ) + return bsearch(&key,T(extratags),S(extratags),sizeof key,(stfu)casort); + + return 0; } -static int populated = 0; - - -/* load in the standard collection of html tags that markdown supports - */ -void -mkd_prepare_tags() -{ - -#define KW(x) mkd_define_tag(x, 0) -#define SC(x) mkd_define_tag(x, 1) - - if ( populated ) return; - populated = 1; - - KW("STYLE"); - KW("SCRIPT"); - KW("ADDRESS"); - KW("BDO"); - KW("BLOCKQUOTE"); - KW("CENTER"); - KW("DFN"); - KW("DIV"); - KW("OBJECT"); - KW("H1"); - KW("H2"); - KW("H3"); - KW("H4"); - KW("H5"); - KW("H6"); - KW("LISTING"); - KW("NOBR"); - KW("UL"); - KW("P"); - KW("OL"); - KW("DL"); - KW("PLAINTEXT"); - KW("PRE"); - KW("TABLE"); - KW("WBR"); - KW("XMP"); - SC("HR"); - SC("BR"); - KW("IFRAME"); - KW("MAP"); - - mkd_sort_tags(); -} /* mkd_prepare_tags */ - - -/* destroy the blocktags list (for shared libraries) +/* destroy the extratags list (for shared libraries) */ void mkd_deallocate_tags() { - if ( S(blocktags) > 0 ) { - populated = 0; - DELETE(blocktags); - } + if ( S(extratags) > 0 ) + DELETE(extratags); } /* mkd_deallocate_tags */