File indexing completed on 2024-04-28 11:21:09
0001 /* markdown: a C implementation of John Gruber's Markdown markup language. 0002 * 0003 * Copyright (C) 2007-2011 David L Parsons. 0004 * The redistribution terms are provided in the COPYRIGHT file that must 0005 * be distributed with this source code. 0006 */ 0007 0008 #include <stdio.h> 0009 #include <stdlib.h> 0010 #include <limits.h> 0011 #include <mkdio.h> 0012 #include <errno.h> 0013 #include <string.h> 0014 #include <stdarg.h> 0015 0016 #include "config.h" 0017 #include "amalloc.h" 0018 0019 #if HAVE_LIBGEN_H 0020 #include <libgen.h> 0021 #endif 0022 0023 static struct _opt { 0024 char *name; 0025 char *desc; 0026 int off; 0027 int skip; /* this opt is a synonym */ 0028 int sayenable; 0029 mkd_flag_t flag; 0030 } opts[] = { 0031 { "tabstop", "default (4-space) tabstops", 0, 0, 1, MKD_TABSTOP }, 0032 { "image", "images", 1, 0, 1, MKD_NOIMAGE }, 0033 { "links", "links", 1, 0, 1, MKD_NOLINKS }, 0034 { "relax", "emphasis inside words", 1, 1, 1, MKD_STRICT }, 0035 { "strict", "emphasis inside words", 0, 0, 1, MKD_STRICT }, 0036 { "tables", "tables", 1, 0, 1, MKD_NOTABLES }, 0037 { "header", "pandoc-style headers", 1, 0, 1, MKD_NOHEADER }, 0038 { "html", "raw html", 1, 0, 1, MKD_NOHTML }, 0039 { "ext", "extended protocols", 1, 0, 1, MKD_NO_EXT }, 0040 { "cdata", "generate cdata", 0, 0, 0, MKD_CDATA }, 0041 { "smarty", "smartypants", 1, 0, 1, MKD_NOPANTS }, 0042 { "pants", "smartypants", 1, 1, 1, MKD_NOPANTS }, 0043 { "toc", "tables of contents", 0, 0, 1, MKD_TOC }, 0044 { "autolink", "autolinking", 0, 0, 1, MKD_AUTOLINK }, 0045 { "safelink", "safe links", 0, 0, 1, MKD_SAFELINK }, 0046 { "strikethrough", "strikethrough", 1, 0, 1, MKD_NOSTRIKETHROUGH }, 0047 { "del", "strikethrough", 1, 1, 1, MKD_NOSTRIKETHROUGH }, 0048 { "superscript", "superscript", 1, 0, 1, MKD_NOSUPERSCRIPT }, 0049 { "emphasis", "emphasis inside words", 0, 0, 1, MKD_NORELAXED }, 0050 { "divquote", ">%class% blockquotes", 1, 0, 1, MKD_NODIVQUOTE }, 0051 { "alphalist", "alpha lists", 1, 0, 1, MKD_NOALPHALIST }, 0052 { "definitionlist","definition lists", 1, 0, 1, MKD_NODLIST }, 0053 { "1.0", "markdown 1.0 compatibility", 0, 0, 1, MKD_1_COMPAT }, 0054 { "footnotes", "markdown extra footnotes", 0, 0, 1, MKD_EXTRA_FOOTNOTE }, 0055 { "footnote", "markdown extra footnotes", 0, 1, 1, MKD_EXTRA_FOOTNOTE }, 0056 { "style", "extract style blocks", 1, 0, 1, MKD_NOSTYLE }, 0057 { "dldiscount", "discount-style definition lists", 1, 0, 1, MKD_NODLDISCOUNT }, 0058 { "dlextra", "extra-style definition lists", 0, 0, 1, MKD_DLEXTRA }, 0059 { "fencedcode", "fenced code blocks", 0, 0, 1, MKD_FENCEDCODE }, 0060 { "idanchor", "id= anchors in TOC", 0, 0, 1, MKD_IDANCHOR }, 0061 { "githubtags", "permit - and _ in element names", 0, 0, 0, MKD_GITHUBTAGS }, 0062 { "urlencodedanchor", "html5-style anchors", 0, 0, 0, MKD_URLENCODEDANCHOR }, 0063 { "html5anchor", "html5-style anchors", 0, 1, 0, MKD_URLENCODEDANCHOR }, 0064 { "latex", "handle LaTeX escapes", 0, 0, 1, MKD_LATEX }, 0065 { "explicitlist", "do not merge adjacent numeric/bullet lists", 0, 0, 1, MKD_EXPLICITLIST }, 0066 } ; 0067 0068 #define NR(x) (sizeof x / sizeof x[0]) 0069 0070 0071 typedef int (*stfu)(const void *, const void *); 0072 0073 int 0074 sort_by_name(struct _opt *a, struct _opt *b) 0075 { 0076 return strcmp(a->name,b->name); 0077 } 0078 0079 int 0080 sort_by_flag(struct _opt *a, struct _opt *b) 0081 { 0082 return a->flag - b->flag; 0083 } 0084 0085 0086 void 0087 show_flags(int byname, int verbose) 0088 { 0089 int i; 0090 0091 if ( byname ) { 0092 qsort(opts, NR(opts), sizeof(opts[0]), (stfu)sort_by_name); 0093 0094 for (i=0; i < NR(opts); i++) 0095 if ( verbose || !opts[i].skip ) 0096 fprintf(stderr, "%16s : %s\n", opts[i].name, opts[i].desc); 0097 } 0098 else { 0099 qsort(opts, NR(opts), sizeof(opts[0]), (stfu)sort_by_flag); 0100 0101 for (i=0; i < NR(opts); i++) 0102 if ( !opts[i].skip ) { 0103 fprintf(stderr, "%08lx : ", (long)opts[i].flag); 0104 if ( opts[i].sayenable ) 0105 fprintf(stderr, opts[i].off ? "disable " : "enable "); 0106 fprintf(stderr, "%s\n", opts[i].desc); 0107 } 0108 } 0109 } 0110 0111 0112 char * 0113 set_flag(mkd_flag_t *flags, char *optionstring) 0114 { 0115 int i; 0116 int enable; 0117 char *arg; 0118 0119 for ( arg = strtok(optionstring, ","); arg; arg = strtok(NULL, ",") ) { 0120 if ( *arg == '+' || *arg == '-' ) 0121 enable = (*arg++ == '+') ? 1 : 0; 0122 else if ( strncasecmp(arg, "no", 2) == 0 ) { 0123 arg += 2; 0124 enable = 0; 0125 } 0126 else 0127 enable = 1; 0128 0129 for ( i=0; i < NR(opts); i++ ) 0130 if ( strcasecmp(arg, opts[i].name) == 0 ) 0131 break; 0132 0133 if ( i < NR(opts) ) { 0134 if ( opts[i].off ) 0135 enable = !enable; 0136 0137 if ( enable ) 0138 *flags |= opts[i].flag; 0139 else 0140 *flags &= ~opts[i].flag; 0141 } 0142 else 0143 return arg; 0144 } 0145 return 0; 0146 }