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 }