pgm_options.c 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. /* markdown: a C implementation of John Gruber's Markdown markup language.
  2. *
  3. * Copyright (C) 2007-2011 David L Parsons.
  4. * The redistribution terms are provided in the COPYRIGHT file that must
  5. * be distributed with this source code.
  6. */
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. #include <limits.h>
  10. #include <errno.h>
  11. #include <string.h>
  12. #include <stdarg.h>
  13. #include "config.h"
  14. #include "markdown.h"
  15. #include "amalloc.h"
  16. #if HAVE_LIBGEN_H
  17. #include <libgen.h>
  18. #endif
  19. static void set_dlist(mkd_flag_t *flags, int enable);
  20. extern void ___mkd_strict_mode(mkd_flag_t *flags, int enable);
  21. static struct _special {
  22. char *name;
  23. void (*setter)(mkd_flag_t *, int);
  24. } special[] = {
  25. { "definitionlist", set_dlist },
  26. { "dlist", set_dlist },
  27. { "standard", ___mkd_strict_mode },
  28. };
  29. static struct _opt {
  30. char *name;
  31. char *desc;
  32. int special;
  33. int off;
  34. int alias; /* this opt is a synonym; don't display in -F? */
  35. int sayenable;
  36. int flag; /* flag to set/clear */
  37. int unflag; /* flag to clear/set */
  38. } opts[] = {
  39. { "tabstop", "default (4-space) tabstops", 0, 0, 0, 1, MKD_TABSTOP },
  40. { "image", "images", 0, 1, 0, 1, MKD_NOIMAGE },
  41. { "links", "links", 0, 1, 0, 1, MKD_NOLINKS },
  42. { "strict", "emphasis inside words", 0, 0, 0, 1, MKD_NORELAXED },
  43. { "relax", "emphasis inside words", 0, 1, 1, 1, MKD_NORELAXED },
  44. { "tables", "tables", 0, 1, 0, 1, MKD_NOTABLES },
  45. { "header", "pandoc-style headers", 0, 1, 0, 1, MKD_NOHEADER },
  46. { "html", "allow raw html", 0, 1, 0, 0, MKD_NOHTML },
  47. { "ext", "extended protocols", 0, 1, 0, 1, MKD_NO_EXT },
  48. { "cdata", "generate cdata", 0, 0, 0, 0, MKD_CDATA },
  49. { "smarty", "smartypants", 0, 1, 0, 1, MKD_NOPANTS },
  50. { "pants", "smartypants", 0, 1, 1, 1, MKD_NOPANTS },
  51. { "toc", "tables of contents", 0, 0, 0, 1, MKD_TOC },
  52. { "autolink", "autolinking", 0, 0, 0, 1, MKD_AUTOLINK },
  53. { "safelink", "safe links", 0, 0, 0, 1, MKD_SAFELINK },
  54. { "strikethrough", "strikethrough", 0, 1, 0, 1, MKD_NOSTRIKETHROUGH },
  55. { "del", "strikethrough", 0, 1, 1, 1, MKD_NOSTRIKETHROUGH },
  56. { "superscript", "superscript", 0, 1, 0, 1, MKD_NOSUPERSCRIPT },
  57. { "divquote", ">%class% blockquotes", 0, 1, 0, 1, MKD_NODIVQUOTE },
  58. { "alphalist", "alpha lists", 0, 1, 0, 1, MKD_NOALPHALIST },
  59. { "1.0", "markdown 1.0 compatibility", 0, 0, 0, 1, MKD_1_COMPAT },
  60. { "footnotes", "markdown extra footnotes", 0, 0, 0, 1, MKD_EXTRA_FOOTNOTE },
  61. { "footnote", "markdown extra footnotes", 0, 0, 1, 1, MKD_EXTRA_FOOTNOTE },
  62. { "style", "extract style blocks", 0, 1, 0, 1, MKD_NOSTYLE },
  63. { "dldiscount", "discount-style definition lists", 0, 0, 0, 1, MKD_DLDISCOUNT },
  64. { "dlextra", "markdown extra-style definition lists", 0, 0, 0, 1, MKD_DLEXTRA },
  65. { "fencedcode", "fenced code blocks", 0, 0, 0, 1, MKD_FENCEDCODE },
  66. { "idanchor", "id= anchors in TOC", 0, 0, 0, 1, MKD_IDANCHOR },
  67. { "githubtags", "- and _ in element names", 0, 0, 0, 1, MKD_GITHUBTAGS },
  68. { "urlencodedanchor", "html5-style anchors", 0, 0, 0, 1, MKD_URLENCODEDANCHOR },
  69. { "html5anchor", "html5-style anchors", 0, 0, 1, 1, MKD_URLENCODEDANCHOR },
  70. { "latex", "LaTeX escapes", 0, 0, 0, 1, MKD_LATEX },
  71. { "explicitlist", "merge adjacent numeric/bullet lists", 0, 0, 0, 0, MKD_EXPLICITLIST },
  72. { "github-listitem","github-style check items", 0, 1, 0, 1, MKD_NORMAL_LISTITEM } ,
  73. { "regular-listitem","github-style check items", 0, 0, 1, 1, MKD_NORMAL_LISTITEM } ,
  74. { "definitionlist","both discount & markdown extra definition lists", 1 },
  75. { "dlist", "both discount & markdown extra definition lists", 1, 0, 1 },
  76. { "standard", "conform to the markdown standard", 1 },
  77. } ;
  78. #define NR(x) (sizeof x / sizeof x[0])
  79. typedef int (*stfu)(const void *, const void *);
  80. int
  81. sort_by_name(struct _opt *a, struct _opt *b)
  82. {
  83. return strcmp(a->name,b->name);
  84. }
  85. int
  86. sort_by_flag(struct _opt *a, struct _opt *b)
  87. {
  88. return a->flag - b->flag;
  89. }
  90. void
  91. show_flags(int byname, int verbose, mkd_flag_t *flags)
  92. {
  93. int i;
  94. if ( byname ) {
  95. qsort(opts, NR(opts), sizeof(opts[0]), (stfu)sort_by_name);
  96. for (i=0; i < NR(opts); i++) {
  97. if ( opts[i].alias && !verbose )
  98. continue;
  99. if ( (flags==0) || is_flag_set(flags, opts[i].flag) )
  100. fprintf(stderr, "%16s : %s\n", opts[i].name, opts[i].desc);
  101. }
  102. }
  103. else {
  104. qsort(opts, NR(opts), sizeof(opts[0]), (stfu)sort_by_flag);
  105. for (i=0; i < NR(opts) && i < 8*sizeof(DWORD); i++) {
  106. if ( opts[i].special || opts[i].alias )
  107. continue;
  108. if ( (flags==0) || is_flag_set(flags, opts[i].flag) ) {
  109. fprintf(stderr, "%08lx : ", 1L<<opts[i].flag);
  110. if ( opts[i].sayenable )
  111. fprintf(stderr, opts[i].off ? "disable " : "enable ");
  112. fprintf(stderr, "%s\n", opts[i].desc);
  113. }
  114. }
  115. }
  116. }
  117. static void
  118. handle_special(mkd_flag_t *flags, char *opt, int enable)
  119. {
  120. int i;
  121. for (i=0; i < NR(special); i++)
  122. if ( strcasecmp(opt, special[i].name) == 0 ) {
  123. (special[i].setter)(flags, enable);
  124. return;
  125. }
  126. }
  127. char *
  128. mkd_set_flag_string(mkd_flag_t *flags, char *optionstring)
  129. {
  130. int i;
  131. int enable;
  132. char *arg;
  133. if ( flags == 0 ) /* shouldn't happen */
  134. return "NULL";
  135. for ( arg = strtok(optionstring, ","); arg; arg = strtok(NULL, ",") ) {
  136. if ( *arg == '+' || *arg == '-' )
  137. enable = (*arg++ == '+') ? 1 : 0;
  138. else if ( strncasecmp(arg, "no", 2) == 0 ) {
  139. arg += 2;
  140. enable = 0;
  141. }
  142. else
  143. enable = 1;
  144. for ( i=0; i < NR(opts); i++ )
  145. if ( strcasecmp(arg, opts[i].name) == 0 )
  146. break;
  147. if ( i < NR(opts) ) {
  148. if ( opts[i].special ) {
  149. handle_special(flags, opts[i].name, enable);
  150. continue;
  151. }
  152. if ( opts[i].off )
  153. enable = !enable;
  154. if ( enable ) {
  155. set_mkd_flag(flags, opts[i].flag);
  156. if ( opts[i].unflag )
  157. clear_mkd_flag(flags, opts[i].unflag);
  158. }
  159. else {
  160. clear_mkd_flag(flags, opts[i].flag);
  161. if ( opts[i].unflag )
  162. set_mkd_flag(flags, opts[i].unflag);
  163. }
  164. }
  165. else
  166. return arg;
  167. }
  168. return 0;
  169. }
  170. static void
  171. set_dlist(mkd_flag_t *flags, int enable)
  172. {
  173. if ( enable ) {
  174. set_mkd_flag(flags, MKD_DLDISCOUNT);
  175. set_mkd_flag(flags, MKD_DLEXTRA);
  176. }
  177. else {
  178. clear_mkd_flag(flags, MKD_DLDISCOUNT);
  179. clear_mkd_flag(flags, MKD_DLEXTRA);
  180. }
  181. }