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 }