cmark
My personal build of CMark ✏️
main.c (5870B)
1 #include <stdlib.h> 2 #include <stdio.h> 3 #include <string.h> 4 #include <errno.h> 5 #include "config.h" 6 #include "cmark.h" 7 #include "node.h" 8 9 #if defined(__OpenBSD__) 10 # include <sys/param.h> 11 # if OpenBSD >= 201605 12 # define USE_PLEDGE 13 # include <unistd.h> 14 # endif 15 #endif 16 17 #if defined(_WIN32) && !defined(__CYGWIN__) 18 #include <io.h> 19 #include <fcntl.h> 20 #endif 21 22 typedef enum { 23 FORMAT_NONE, 24 FORMAT_HTML, 25 FORMAT_XML, 26 FORMAT_MAN, 27 FORMAT_COMMONMARK, 28 FORMAT_LATEX 29 } writer_format; 30 31 void print_usage() { 32 printf("Usage: cmark [FILE*]\n"); 33 printf("Options:\n"); 34 printf(" --to, -t FORMAT Specify output format (html, xml, man, " 35 "commonmark, latex)\n"); 36 printf(" --width WIDTH Specify wrap width (default 0 = nowrap)\n"); 37 printf(" --sourcepos Include source position attribute\n"); 38 printf(" --hardbreaks Treat newlines as hard line breaks\n"); 39 printf(" --nobreaks Render soft line breaks as spaces\n"); 40 printf(" --safe Omit raw HTML and dangerous URLs\n"); 41 printf(" --unsafe Render raw HTML and dangerous URLs\n"); 42 printf(" --smart Use smart punctuation\n"); 43 printf(" --validate-utf8 Replace invalid UTF-8 sequences with U+FFFD\n"); 44 printf(" --help, -h Print usage information\n"); 45 printf(" --version Print version\n"); 46 } 47 48 static void print_document(cmark_node *document, writer_format writer, 49 int options, int width) { 50 char *result; 51 52 switch (writer) { 53 case FORMAT_HTML: 54 result = cmark_render_html(document, options); 55 break; 56 case FORMAT_XML: 57 result = cmark_render_xml(document, options); 58 break; 59 case FORMAT_MAN: 60 result = cmark_render_man(document, options, width); 61 break; 62 case FORMAT_COMMONMARK: 63 result = cmark_render_commonmark(document, options, width); 64 break; 65 case FORMAT_LATEX: 66 result = cmark_render_latex(document, options, width); 67 break; 68 default: 69 fprintf(stderr, "Unknown format %d\n", writer); 70 exit(1); 71 } 72 printf("%s", result); 73 document->mem->free(result); 74 } 75 76 int main(int argc, char *argv[]) { 77 int i, numfps = 0; 78 int *files; 79 char buffer[4096]; 80 cmark_parser *parser; 81 size_t bytes; 82 cmark_node *document; 83 int width = 0; 84 char *unparsed; 85 writer_format writer = FORMAT_HTML; 86 int options = CMARK_OPT_DEFAULT; 87 88 #ifdef USE_PLEDGE 89 if (pledge("stdio rpath", NULL) != 0) { 90 perror("pledge"); 91 return 1; 92 } 93 #endif 94 95 #if defined(_WIN32) && !defined(__CYGWIN__) 96 _setmode(_fileno(stdin), _O_BINARY); 97 _setmode(_fileno(stdout), _O_BINARY); 98 #endif 99 100 files = (int *)calloc(argc, sizeof(*files)); 101 102 for (i = 1; i < argc; i++) { 103 if (strcmp(argv[i], "--version") == 0) { 104 printf("cmark %s", CMARK_VERSION_STRING); 105 printf(" - CommonMark converter\n(C) 2014-2016 John MacFarlane\n"); 106 exit(0); 107 } else if (strcmp(argv[i], "--sourcepos") == 0) { 108 options |= CMARK_OPT_SOURCEPOS; 109 } else if (strcmp(argv[i], "--hardbreaks") == 0) { 110 options |= CMARK_OPT_HARDBREAKS; 111 } else if (strcmp(argv[i], "--nobreaks") == 0) { 112 options |= CMARK_OPT_NOBREAKS; 113 } else if (strcmp(argv[i], "--smart") == 0) { 114 options |= CMARK_OPT_SMART; 115 } else if (strcmp(argv[i], "--safe") == 0) { 116 options |= CMARK_OPT_SAFE; 117 } else if (strcmp(argv[i], "--unsafe") == 0) { 118 options |= CMARK_OPT_UNSAFE; 119 } else if (strcmp(argv[i], "--validate-utf8") == 0) { 120 options |= CMARK_OPT_VALIDATE_UTF8; 121 } else if ((strcmp(argv[i], "--help") == 0) || 122 (strcmp(argv[i], "-h") == 0)) { 123 print_usage(); 124 exit(0); 125 } else if (strcmp(argv[i], "--width") == 0) { 126 i += 1; 127 if (i < argc) { 128 width = (int)strtol(argv[i], &unparsed, 10); 129 if (unparsed && strlen(unparsed) > 0) { 130 fprintf(stderr, "failed parsing width '%s' at '%s'\n", argv[i], 131 unparsed); 132 exit(1); 133 } 134 } else { 135 fprintf(stderr, "--width requires an argument\n"); 136 exit(1); 137 } 138 } else if ((strcmp(argv[i], "-t") == 0) || (strcmp(argv[i], "--to") == 0)) { 139 i += 1; 140 if (i < argc) { 141 if (strcmp(argv[i], "man") == 0) { 142 writer = FORMAT_MAN; 143 } else if (strcmp(argv[i], "html") == 0) { 144 writer = FORMAT_HTML; 145 } else if (strcmp(argv[i], "xml") == 0) { 146 writer = FORMAT_XML; 147 } else if (strcmp(argv[i], "commonmark") == 0) { 148 writer = FORMAT_COMMONMARK; 149 } else if (strcmp(argv[i], "latex") == 0) { 150 writer = FORMAT_LATEX; 151 } else { 152 fprintf(stderr, "Unknown format %s\n", argv[i]); 153 exit(1); 154 } 155 } else { 156 fprintf(stderr, "No argument provided for %s\n", argv[i - 1]); 157 exit(1); 158 } 159 } else if (*argv[i] == '-') { 160 print_usage(); 161 exit(1); 162 } else { // treat as file argument 163 files[numfps++] = i; 164 } 165 } 166 167 parser = cmark_parser_new(options); 168 for (i = 0; i < numfps; i++) { 169 FILE *fp = fopen(argv[files[i]], "rb"); 170 if (fp == NULL) { 171 fprintf(stderr, "Error opening file %s: %s\n", argv[files[i]], 172 strerror(errno)); 173 exit(1); 174 } 175 176 while ((bytes = fread(buffer, 1, sizeof(buffer), fp)) > 0) { 177 cmark_parser_feed(parser, buffer, bytes); 178 if (bytes < sizeof(buffer)) { 179 break; 180 } 181 } 182 183 fclose(fp); 184 } 185 186 if (numfps == 0) { 187 188 while ((bytes = fread(buffer, 1, sizeof(buffer), stdin)) > 0) { 189 cmark_parser_feed(parser, buffer, bytes); 190 if (bytes < sizeof(buffer)) { 191 break; 192 } 193 } 194 } 195 196 #ifdef USE_PLEDGE 197 if (pledge("stdio", NULL) != 0) { 198 perror("pledge"); 199 return 1; 200 } 201 #endif 202 203 document = cmark_parser_finish(parser); 204 cmark_parser_free(parser); 205 206 print_document(document, writer, options, width); 207 208 cmark_node_free(document); 209 210 free(files); 211 212 return 0; 213 }