/* * markdown: convert a single markdown document into html */ /* * Copyright (C) 2007 Jessica L Parsons. * The redistribution terms are provided in the COPYRIGHT file that must * be distributed with this source code. */ #include #include #include #include #include #include #include #include #include #include #include "config.h" #include "amalloc.h" #include "pgm_options.h" #include "tags.h" #include "gethopt.h" #if HAVE_LIBGEN_H #include #endif #ifndef HAVE_BASENAME char* basename(char *p) { char *ret = strrchr(p, '/'); return ret ? (1+ret) : p; } #endif char *pgm = "markdown"; char * e_flags(const char *text, const int size, void *context) { return (char*)context; } void complain(char *fmt, ...) { va_list ptr; fprintf(stderr, "%s: ", pgm); va_start(ptr, fmt); vfprintf(stderr, fmt, ptr); va_end(ptr); fputc('\n', stderr); fflush(stderr); } void callback_free(char *input, int size, void *ctx) { if (input) free(input); } char * anchor_format(char *input, void *ctx) { int i, j, size; char* ret; if ( !input ) return NULL; size = strlen(input); ret = malloc(1+size); if ( !ret ) return NULL; while ( size && isspace(input[size-1]) ) --size; for ( j=i=0; i < size; i++ ) { if (isalnum(input[i]) || strchr("-_+", input[i]) ) ret[j++] = input[i]; else if ( input[i] == ' ' ) ret[j++] = '-'; } ret[j++] = 0; return ret; } char *external_formatter = 0; #define RECEIVER 0 #define SENDER 1 char * external_codefmt(char *src, int len, char *lang) { int child_status; int size, bufsize, curr; char *res; pid_t child; int tochild[2], toparent[2]; if ( pipe(tochild) != 0 || pipe(toparent) != 0 ) { perror("external_codefmt (pipe)"); res = malloc(len+1); strcpy(res, src); return res; } if ( (child = fork()) > 0 ) { close(tochild[RECEIVER]); close(toparent[SENDER]); bufsize = 1000; res = malloc(1+bufsize); curr = 0; /* parent */ write(tochild[SENDER], src, len); close(tochild[SENDER]); while ( (size = read(toparent[RECEIVER], res+curr, 1000)) > 0 ) { curr += size; res = realloc(res, bufsize += 1000); } res[curr] = 0; waitpid(child, &child_status, 0); close(toparent[RECEIVER]); if ( WIFEXITED(child_status) ) return res; else free(res); /* something failed; just return the original string */ } else if ( child == 0 ) { close(tochild[SENDER]); close(toparent[RECEIVER]); close(1); dup2(toparent[SENDER], 1); close(0); dup2(tochild[RECEIVER], 0); system(external_formatter); close(0); close(tochild[RECEIVER]); close(1); close(toparent[SENDER]); exit(0); } res = malloc(len+1); strcpy(res, src); return res; } struct h_opt opts[] = { { 0, "html5", '5', 0, "recognise html5 block elements" }, { 0, "base", 'b', "url-base", "URL prefix" }, { 0, "debug", 'd', 0, "debugging" }, { 0, "version",'V', 0, "show version info" }, { 0, 0, 'E', "flags", "url flags" }, { 0, 0, 'F', "bitmap", "set/show hex flags" }, { 0, 0, 'f', "{+-}flags", "set/show named flags" }, { 0, 0, 'G', 0, "github flavoured markdown" }, { 0, 0, 'n', 0, "don't write generated html" }, { 0, 0, 's', "text", "format `text`" }, { 0, "style", 'S', 0, "output