pax_global_header00006660000000000000000000000064122251644230014513gustar00rootroot0000000000000052 comment=49abed29e7d806414e31967c1f4010a40d585c61 discount-2.1.7/000077500000000000000000000000001222516442300133525ustar00rootroot00000000000000discount-2.1.7/COPYRIGHT000066400000000000000000000027541222516442300146550ustar00rootroot00000000000000->Copyright (C) 2007 David Loren Parsons. All rights reserved.<- Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of works must retain the original copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the original copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither my name (David L Parsons) nor the names of contributors to this code may be used to endorse or promote products derived from this work without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. discount-2.1.7/CREDITS000066400000000000000000000030241222516442300143710ustar00rootroot00000000000000Discount is primarily my work, but it has only reached the point where it is via contributions, critiques, and bug reports from a host of other people, some of which are listed before. If your name isn't on this list, please remind me -david parsons (orc@pell.chi.il.us) Josh Wood -- Plan9 support. Mike Schiraldi -- Reddit style automatic links, MANY MANY MANY bug reports about boundary conditions and places where I didn't get it right. Jjgod Jiang -- Table of contents support. Petite Abeille -- Many bug reports about places where I didn't get it right. Tim Channon -- inspiration for the `mkd_xhtmlpage()` function Christian Herenz-- Many bug reports regarding my implementation of `[]()` and `![]()` A.S.Bradbury -- Portability bug reports for 64 bit systems. Joyent -- Loan of a solaris box so I could get discount working under solaris. Ryan Tomayko -- Portability requests (and the rdiscount ruby binding.) yidabu -- feedback on the documentation, bug reports against utf-8 support. Pierre Joye -- bug reports, php discount binding. Masayoshi Sekimura- perl discount binding. Jeremy Hinegardner- bug reports about list handling. Andrew White -- bug reports about the format of generated urls. Steve Huff -- bug reports about Makefile portability (for Fink) Ignacio Burgue?o-- bug reports about `>%class%` Henrik Nyh -- bug reports about embedded html handling. John J. Foerch -- bug reports about incorrect `–` and `—` translations. discount-2.1.7/Csio.c000066400000000000000000000017601222516442300144170ustar00rootroot00000000000000#include #include #include #include "cstring.h" #include "markdown.h" #include "amalloc.h" /* putc() into a cstring */ void Csputc(int c, Cstring *iot) { EXPAND(*iot) = c; } /* printf() into a cstring */ int Csprintf(Cstring *iot, char *fmt, ...) { va_list ptr; int siz=100; do { RESERVE(*iot, siz); va_start(ptr, fmt); siz = vsnprintf(T(*iot)+S(*iot), ALLOCATED(*iot)-S(*iot), fmt, ptr); va_end(ptr); } while ( siz > (ALLOCATED(*iot)-S(*iot)) ); S(*iot) += siz; return siz; } /* write() into a cstring */ int Cswrite(Cstring *iot, char *bfr, int size) { RESERVE(*iot, size); memcpy(T(*iot)+S(*iot), bfr, size); S(*iot) += size; return size; } /* reparse() into a cstring */ void Csreparse(Cstring *iot, char *buf, int size, int flags) { MMIOT f; ___mkd_initmmiot(&f, 0); ___mkd_reparse(buf, size, 0, &f, 0); ___mkd_emblock(&f); SUFFIX(*iot, T(f.out), S(f.out)); ___mkd_freemmiot(&f, 0); } discount-2.1.7/INSTALL000066400000000000000000000033041222516442300144030ustar00rootroot00000000000000 HOW TO BUILD AND INSTALL DISCOUNT 1) Unpacking the distribution The DISCOUNT sources are distributed in tarballs. After extracting from the tarball, you should end up with all the source and build files in the directory discount-(version) 2) Installing the distribution DISCOUNT uses configure.sh to set itself up for compilation. To run configure, just do ``./configure.sh'' and it will check your system for build dependencies and build makefiles for you. If configure.sh finishes without complaint, you can then do a ``make'' to compile everything and a ``make install'' to install the binaries. Configure.sh has a few options that can be set: --src=DIR where the source lives (.) --prefix=DIR where to install the final product (/usr/local) --execdir=DIR where to put executables (prefix/bin) --sbindir=DIR where to put static executables (prefix/sbin) --confdir=DIR where to put configuration information (/etc) --libdir=DIR where to put libraries (prefix/lib) --libexecdir=DIR where to put private executables --mandir=DIR where to put manpages --enable-dl-tag Use the DL tag extension --enable-pandoc-header Use pandoc-style header blocks --enable-superscript A^B expands to AB --enable-amalloc Use a debugging memory allocator (to detect leaks) --relaxed-emphasis Don't treat _ in the middle of a word as emphasis --with-tabstops=N Set tabstops to N characters (default is 4) 3) Installing sample programs and manpages The standard ``make install'' rule just installs the binaries. If you want to install the sample programs, they are installed with ``make install.samples''; to install manpages, ``make install.man''. A shortcut to install everything is ``make install.everything'' discount-2.1.7/Makefile.in000066400000000000000000000107311222516442300154210ustar00rootroot00000000000000CC=@CC@ -I. LFLAGS=-L. CFLAGS=@CFLAGS@ AR=@AR@ RANLIB=@RANLIB@ BINDIR=@exedir@ MANDIR=@mandir@ LIBDIR=@libdir@ INCDIR=@prefix@/include PGMS=markdown SAMPLE_PGMS=mkd2html makepage @THEME@SAMPLE_PGMS+= theme MKDLIB=libmarkdown OBJS=mkdio.o markdown.o dumptree.o generate.o \ resource.o docheader.o version.o toc.o css.o \ xml.o Csio.o xmlpage.o basename.o emmatch.o \ github_flavoured.o setup.o tags.o html5.o flags.o @AMALLOC@ TESTFRAMEWORK=echo cols MAN3PAGES=mkd-callbacks.3 mkd-functions.3 markdown.3 mkd-line.3 all: $(PGMS) $(SAMPLE_PGMS) $(TESTFRAMEWORK) install: $(PGMS) $(DESTDIR)$(BINDIR) $(DESTDIR)$(LIBDIR) $(DESTDIR)$(INCDIR) @INSTALL_PROGRAM@ $(PGMS) $(DESTDIR)$(BINDIR) ./librarian.sh install libmarkdown VERSION $(DESTDIR)$(LIBDIR) @INSTALL_DATA@ mkdio.h $(DESTDIR)$(INCDIR) install.everything: install install.samples install.man install.samples: $(SAMPLE_PGMS) install $(DESTDIR)$(BINDIR) @INSTALL_PROGRAM@ $(SAMPLE_PGMS) $(DESTDIR)$(BINDIR) @INSTALL_DIR@ $(DESTDIR)$(MANDIR)/man1 @INSTALL_DATA@ theme.1 makepage.1 mkd2html.1 $(DESTDIR)$(MANDIR)/man1 install.man: @INSTALL_DIR@ $(DESTDIR)$(MANDIR)/man3 @INSTALL_DATA@ $(MAN3PAGES) $(DESTDIR)$(MANDIR)/man3 for x in mkd_line mkd_generateline; do \ ( echo '.\"' ; echo ".so man3/mkd-line.3" ) > $(DESTDIR)$(MANDIR)/man3/$$x.3;\ done for x in mkd_in mkd_string; do \ ( echo '.\"' ; echo ".so man3/markdown.3" ) > $(DESTDIR)$(MANDIR)/man3/$$x.3;\ done for x in mkd_compile mkd_css mkd_generatecss mkd_generatehtml mkd_cleanup mkd_doc_title mkd_doc_author mkd_doc_date; do \ ( echo '.\"' ; echo ".so man3/mkd-functions.3" ) > $(DESTDIR)$(MANDIR)/man3/$$x.3; \ done @INSTALL_DIR@ $(DESTDIR)$(MANDIR)/man7 @INSTALL_DATA@ markdown.7 mkd-extensions.7 $(DESTDIR)$(MANDIR)/man7 @INSTALL_DIR@ $(DESTDIR)$(MANDIR)/man1 @INSTALL_DATA@ markdown.1 $(DESTDIR)$(MANDIR)/man1 install.everything: install install.man $(DESTDIR)$(BINDIR): @INSTALL_DIR@ $(DESTDIR)$(BINDIR) $(DESTDIR)$(INCDIR): @INSTALL_DIR@ $(DESTDIR)$(INCDIR) $(DESTDIR)$(LIBDIR): @INSTALL_DIR@ $(DESTDIR)$(LIBDIR) version.o: version.c VERSION $(CC) $(CFLAGS) -DVERSION=\"`cat VERSION`\" -c version.c VERSION: @true tags.o: tags.c blocktags blocktags: mktags ./mktags > blocktags # example programs @THEME@theme: theme.o $(MKDLIB) mkdio.h @THEME@ $(CC) $(CFLAGS) $(LFLAGS) -o theme theme.o pgm_options.o -lmarkdown @LIBS@ mkd2html: mkd2html.o $(MKDLIB) mkdio.h $(CC) $(CFLAGS) $(LFLAGS) -o mkd2html mkd2html.o -lmarkdown @LIBS@ markdown: main.o pgm_options.o $(MKDLIB) $(CC) $(CFLAGS) $(LFLAGS) -o markdown main.o pgm_options.o -lmarkdown @LIBS@ makepage: makepage.c pgm_options.o $(MKDLIB) mkdio.h $(CC) $(CFLAGS) $(LFLAGS) -o makepage makepage.c pgm_options.o -lmarkdown @LIBS@ pgm_options.o: pgm_options.c mkdio.h config.h $(CC) $(CFLAGS) -I. -c pgm_options.c main.o: main.c mkdio.h config.h $(CC) $(CFLAGS) -I. -c main.c $(MKDLIB): $(OBJS) ./librarian.sh make $(MKDLIB) VERSION $(OBJS) verify: echo tools/checkbits.sh @./echo -n "headers ... "; tools/checkbits.sh && echo "GOOD" test: $(PGMS) $(TESTFRAMEWORK) verify @for x in tests/*.t; do \ @LD_LIBRARY_PATH@=`pwd` sh $$x || exit 1; \ done cols: tools/cols.c config.h $(CC) -o cols tools/cols.c echo: tools/echo.c config.h $(CC) -o echo tools/echo.c clean: rm -f $(PGMS) $(TESTFRAMEWORK) $(SAMPLE_PGMS) *.o rm -f $(MKDLIB) `./librarian.sh files $(MKDLIB) VERSION` distclean spotless: clean rm -f @GENERATED_FILES@ @CONFIGURE_FILES@ Csio.o: Csio.c cstring.h amalloc.h config.h markdown.h amalloc.o: amalloc.c basename.o: basename.c config.h cstring.h amalloc.h markdown.h css.o: css.c config.h cstring.h amalloc.h markdown.h docheader.o: docheader.c config.h cstring.h amalloc.h markdown.h dumptree.o: dumptree.c markdown.h cstring.h amalloc.h config.h emmatch.o: emmatch.c config.h cstring.h amalloc.h markdown.h generate.o: generate.c config.h cstring.h amalloc.h markdown.h main.o: main.c config.h amalloc.h pgm_options.o: pgm_options.c pgm_options.h config.h amalloc.h makepage.o: makepage.c markdown.o: markdown.c config.h cstring.h amalloc.h markdown.h mkd2html.o: mkd2html.c config.h mkdio.h cstring.h amalloc.h mkdio.o: mkdio.c config.h cstring.h amalloc.h markdown.h resource.o: resource.c config.h cstring.h amalloc.h markdown.h theme.o: theme.c config.h mkdio.h cstring.h amalloc.h toc.o: toc.c config.h cstring.h amalloc.h markdown.h version.o: version.c config.h xml.o: xml.c config.h cstring.h amalloc.h markdown.h xmlpage.o: xmlpage.c config.h cstring.h amalloc.h markdown.h discount-2.1.7/Plan9/000077500000000000000000000000001222516442300143355ustar00rootroot00000000000000discount-2.1.7/Plan9/README000066400000000000000000000025421222516442300152200ustar00rootroot00000000000000% Discount on Plan 9 % Josh Wood % 2009-06-12 # *Discount* Markdown compiler on Plan 9 ## Build % CONFIG='--enable-all-features' mk config % mk install % markdown -V markdown: discount X.Y.Z DL_TAG HEADER DEBUG SUPERSCRIPT RELAXED DIV `--enable-all-features` may be replaced by zero or more of: --enable-dl-tag Use the DL tag extension --enable-pandoc-header Use pandoc-style header blocks --enable-superscript A^B becomes AB --enable-amalloc Enable memory allocation debugging --relaxed-emphasis underscores aren't special in the middle of words --with-tabstops=N Set tabstops to N characters (default is 4) --enable-div Enable >%id% divisions --enable-alpha-list Enable (a)/(b)/(c) lists --enable-all-features Turn on all stable optional features ## Notes The supplied mkfile merely drives Discount's own configure script and then APE's *psh* environment to build the Discount source, then copies the result(s) to locations appropriate for system-wide use on Plan 9. There are a few other *mk*(1) targets: `install.libs`: Discount includes a C library and header. Installation is optional. Plan 9 binaries are statically linked. `install.man`: Add manual pages for markdown(1) and (6). `install.progs`: Extra programs. *makepage* writes complete XHTML documents, rather than fragments. *mkd2html* is similar, but produces HTML. discount-2.1.7/Plan9/markdown.1000066400000000000000000000050701222516442300162430ustar00rootroot00000000000000.TH MARKDOWN 1 .SH NAME markdown \- convert Markdown text to HTML .SH SYNOPSIS .B markdown [ .B -dTV ] [ .BI -b " url-base ] [ .BI -F " bitmap ] [ .BI -f " flags ] [ .BI -o " ofile ] [ .BI -s " text ] [ .BI -t " text ] [ .I file ] .SH DESCRIPTION The .I markdown utility reads the .IR Markdown (6)-formatted .I file (or standard input) and writes its .SM HTML fragment representation on standard output. .PP The options are: .TF dfdoptions .TP .BI -b " url-base Links in source begining with .B / will be prefixed with .I url-base in the output. .TP .B -d Instead of printing an .SM HTML fragment, print a parse tree. .TP .BI -F " bitmap Set translation flags. .I Bitmap is a bit map of the various configuration options described in .IR markdown (2). .TP .BI -f " flags Set or clear various translation .IR flags , described below. .I Flags are in a comma-delimited list, with an optional .B + (set) prefix on each flag. .TP .BI -o " ofile Write the generated .SM HTML to .IR ofile . .TP .BI -s " text Use the .IR markdown (2) function to format the .I text on standard input. .TP .B -T Under .B -f .BR toc , print the table of contents as an unordered list before the usual .SM HTML output. .TP .BI -t " text Use .IR mkd_text (in .IR markdown (2)) to format .I text instead of processing standard input with .IR markdown . .TP .B -V Show version number and configuration. If the version includes the string .BR DL_TAG , .I markdown was configured with definition list support. If the version includes the string .BR HEADER , .I markdown was configured to support pandoc header blocks. .PD .SS TRANSLATION FLAGS The translation flags understood by .B -f are: .TF \ noheader .TP .B noimage Don't allow image tags. .TP .B nolinks Don't allow links. .TP .B nohtml Don't allow any embedded HTML. .TP .B cdata Generate valid XML output. .TP .B noheader Do not process pandoc headers. .TP .B notables Do not process the syntax extension for tables. .TP .B tabstops Use Markdown-standard 4-space tabstops. .TP .B strict Disable superscript and relaxed emphasis. .TP .B relax Enable superscript and relaxed emphasis (the default). .TP .B toc Enable table of contents support, generated from headings (in .IR markdown (6)) in the source. .TP .B 1.0 Revert to Markdown 1.0 compatibility. .PD .PP For example, .B -f nolinks,quot tells .I markdown not to allow .B tags, and to expand double quotes. .SH SOURCE .B /sys/src/cmd/discount .SH SEE ALSO .IR markdown (2), .IR markdown (6) .PP http://daringfireball.net/projects/markdown/, ``Markdown''. .SH DIAGNOSTICS .I Markdown exits 0 on success and >0 if an error occurs. discount-2.1.7/Plan9/markdown.2000066400000000000000000000126271222516442300162520ustar00rootroot00000000000000.TH MARKDOWN 2 .SH NAME mkd_in, mkd_string, markdown, mkd_compile, mkd_css, mkd_generatecss, mkd_document, mkd_generatehtml, mkd_xhtmlpage, mkd_toc, mkd_generatetoc, mkd_cleanup, mkd_doc_title, mkd_doc_author, mkd_doc_date, mkd_line, mkd_generateline \- convert Markdown text to HTML .SH SYNOPSIS .ta \w'MMIOT* 'u .B #include .PP .B MMIOT* mkd_in(FILE *input, int flags) .PP .B MMIOT* mkd_string(char *buf, int size, int flags) .PP .B int markdown(MMIOT *doc, FILE *output, int flags) .PP .B int mkd_compile(MMIOT *document, int flags) .PP .B int mkd_css(MMIOT *document, char **doc) .PP .B int mkd_generatecss(MMIOT *document, FILE *output) .PP .B int mkd_document(MMIOT *document, char **doc) .PP .B int mkd_generatehtml(MMIOT *document, FILE *output) .PP .B int mkd_xhtmlpage(MMIOT *document, int flags, FILE *output) .PP .B int mkd_toc(MMIOT *document, char **doc) .PP .B int mkd_generatetoc(MMIOT *document, FILE *output) .PP .B void mkd_cleanup(MMIOT*); .PP .B char* mkd_doc_title(MMIOT*) .PP .B char* mkd_doc_author(MMIOT*) .PP .B char* mkd_doc_date(MMIOT*) .PP .B int mkd_line(char *string, int size, char **doc, int flags) .PP .B int mkd_generateline(char *string, int size, FILE *output, int flags) .PD .PP .SH DESCRIPTION These functions convert .IR Markdown (6) text into .SM HTML markup. .PP .I Mkd_in reads the text referenced by pointer to .B FILE .I input and returns a pointer to an .B MMIOT structure of the form expected by .I markdown and the other converters. .I Mkd_string accepts one .I string and returns a pointer to .BR MMIOT . .PP After such preparation, .I markdown converts .I doc and writes the result to .IR output , while .I mkd_compile transforms .I document in-place. .PP One or more of the following .I flags (combined with .BR OR ) control .IR markdown 's processing of .IR doc : .TF MKD_NOIMAGE .TP .B MKD_NOIMAGE Do not process .B ![] and remove .B tags from the output. .TP .B MKD_NOLINKS Do not process .B [] and remove .B tags from the output. .TP .B MKD_NOPANTS Suppress Smartypants-style replacement of quotes, dashes, or ellipses. .TP .B MKD_STRICT Disable superscript and relaxed emphasis processing if configured; otherwise a no-op. .TP .B MKD_TAGTEXT Process as inside an .SM HTML tag: no .BR , no .BR , no .SM HTML or .B [] expansion. .TP .B MKD_NO_EXT Don't process pseudo-protocols (in .IR markdown (6)). .TP .B MKD_CDATA Generate code for .SM XML .B ![CDATA[...]] element. .TP .B MKD_NOHEADER Don't process Pandoc-style headers. .TP .B MKD_TABSTOP When reading documents, expand tabs to 4 spaces, overriding any compile-time configuration. .TP .B MKD_TOC Label headings for use with the .I mkd_generatetoc and .I mkd_toc functions. .TP .B MKD_1_COMPAT MarkdownTest_1.0 compatibility. Trim trailing spaces from first line of code blocks and disable implicit reference links (in .IR markdown (6)). .TP .B MKD_AUTOLINK Greedy .SM URL generation. When set, any .SM URL is converted to a hyperlink, even those not encased in .BR <> . .TP .B MKD_SAFELINK Don't make hyperlinks from .B [][] links that have unknown .SM URL protocol types. .TP .B MKD_NOTABLES Do not process the syntax extension for tables (in .IR markdown (6)). .TP .B MKD_EMBED All of .BR MKD_NOLINKS , .BR MKD_NOIMAGE , and .BR MKD_TAGTEXT . .PD .PP This implementation supports Pandoc-style headers and inline .SM CSS .B at the end of the line or at the beginning of a subsequent line. .IP Style blocks apply to the entire document regardless of where they are defined. .TP Image Dimensions Image specification has been extended with an argument describing image dimensions: .BI = height x width. For an image 400 pixels high and 300 wide, the new syntax is: .IP .EX ![Alt text](/path/to/image.jpg =400x300 "Title") .EE .TP Pseudo-Protocols Pseudo-protocols that may replace the common .B http: or .B mailto: have been added to the link syntax described above. .IP .BR abbr : Text following is used as the .B title attribute of an .B abbr tag wrapping the link text. So .B [LT](abbr:Link Text) gives .B LT. .IP .BR id : The link text is marked up and written to the output, wrapped with .B and .BR . .IP .BR class : The link text is marked up and written to the output, wrapped with .B and .BR . .IP .BR raw : Text following is written to the output with no further processing. The link text is discarded. .TP Alphabetic Lists If .I markdown was configured with .BR --enable-alpha-list , .IP .EX a. this b. is c. an alphabetic d. list .EE .IP yields an .SM HTML .B ol ordered list. .TP Definition Lists If configured with .BR --enable-dl-tag , markup for definition lists is enabled. A definition list item is defined as .IP .EX =term= definition .EE .TP Tables Tables are specified with a pipe .RB ( | ) and dash .RB ( - ) marking. The markdown text .IP .EX header0|header1 -------|------- textA|textB textC|textD .EE .IP will produce an .SM HTML .B table of two columns and three rows. A header row is designated by ``underlining'' with dashes. Declare a column's alignment by affixing a colon .RB ( : ) to the left or right end of the dashes underlining its header. In the output, this yields the corresponding value for the .B align attribute on each .B td cell in the column. A colon at both ends of a column's header dashes indicates center alignment. .TP Relaxed Emphasis If configured with .BR --relaxed-emphasis , the rules for emphasis are changed so that a single .B _ will not count as an emphasis character in the middle of a word. This is useful for documenting some code where .B _ appears frequently, and would normally require a backslash escape. .PD .SH SEE ALSO .IR markdown (1), .IR markdown (2) .PP http://daringfireball.net/projects/markdown/syntax/, ``Markdown: Syntax''. .PP http://daringfireball.net/projects/smartypants/, ``Smarty Pants''. .PP http://michelf.com/projects/php-markdown/extra/#table, ``PHP Markdown Extra: Tables''. discount-2.1.7/Plan9/mkfile000066400000000000000000000013521222516442300155300ustar00rootroot00000000000000BIN=/$objtype/bin CC='cc -D_BSD_EXTENSION -D_C99_SNPRINTF_EXTENSION' markdown: ape/psh -c 'cd .. && make' none:V: markdown test: markdown ape/psh -c 'cd ..&& make test' install: markdown cp ../markdown $BIN/markdown install.progs: install cp ../makepage $BIN/makepage cp ../mkd2html $BIN/mkd2html install.libs: install cp ../mkdio.h /sys/include/ape/mkdio.h cp ../libmarkdown.a /$objtype/lib/ape/libmarkdown.a install.man: install cp markdown.1 /sys/man/1/markdown cp markdown.2 /sys/man/2/markdown cp markdown.6 /sys/man/6/markdown installall:V: install.libs install.man install.progs config: ape/psh -c 'cd .. && ./configure.sh $CONFIG' clean: ape/psh -c 'cd .. && make clean' nuke: ape/psh -c 'cd .. && make distclean' discount-2.1.7/README000066400000000000000000000012601222516442300142310ustar00rootroot00000000000000DISCOUNT is a implementation of John Gruber's Markdown markup language. It implements, as far as I can tell, all of the language as described in and passes the Markdown test suite at DISCOUNT is free software written by David Parsons ; it is released under a BSD-style license that allows you to do as you wish with it as long as you don't attempt to claim it as your own work. Most of the programs included in the DISCOUNT distribution have manual pages describing how they work. The file INSTALL describes how to build and install discount discount-2.1.7/VERSION000066400000000000000000000000061222516442300144160ustar00rootroot000000000000002.1.7 discount-2.1.7/amalloc.c000066400000000000000000000037701222516442300151350ustar00rootroot00000000000000/* * debugging malloc()/realloc()/calloc()/free() that attempts * to keep track of just what's been allocated today. */ #include #include #define MAGIC 0x1f2e3d4c struct alist { int magic, size; struct alist *next, *last; }; static struct alist list = { 0, 0, 0, 0 }; static int mallocs=0; static int reallocs=0; static int frees=0; void * acalloc(int size, int count) { struct alist *ret = calloc(size + sizeof(struct alist), count); if ( ret ) { ret->magic = MAGIC; ret->size = size * count; if ( list.next ) { ret->next = list.next; ret->last = &list; ret->next->last = ret; list.next = ret; } else { ret->last = ret->next = &list; list.next = list.last = ret; } ++mallocs; return ret+1; } return 0; } void* amalloc(int size) { return acalloc(size,1); } void afree(void *ptr) { struct alist *p2 = ((struct alist*)ptr)-1; if ( p2->magic == MAGIC ) { p2->last->next = p2->next; p2->next->last = p2->last; ++frees; free(p2); } else free(ptr); } void * arealloc(void *ptr, int size) { struct alist *p2 = ((struct alist*)ptr)-1; struct alist save; if ( p2->magic == MAGIC ) { save.next = p2->next; save.last = p2->last; p2 = realloc(p2, sizeof(*p2) + size); if ( p2 ) { p2->size = size; p2->next->last = p2; p2->last->next = p2; ++reallocs; return p2+1; } else { save.next->last = save.last; save.last->next = save.next; return 0; } } return realloc(ptr, size); } void adump() { struct alist *p; for ( p = list.next; p && (p != &list); p = p->next ) { fprintf(stderr, "allocated: %d byte%s\n", p->size, (p->size==1) ? "" : "s"); fprintf(stderr, " [%.*s]\n", p->size, (char*)(p+1)); } if ( getenv("AMALLOC_STATISTICS") ) { fprintf(stderr, "%d malloc%s\n", mallocs, (mallocs==1)?"":"s"); fprintf(stderr, "%d realloc%s\n", reallocs, (reallocs==1)?"":"s"); fprintf(stderr, "%d free%s\n", frees, (frees==1)?"":"s"); } } discount-2.1.7/amalloc.h000066400000000000000000000007541222516442300151410ustar00rootroot00000000000000/* * debugging malloc()/realloc()/calloc()/free() that attempts * to keep track of just what's been allocated today. */ #ifndef AMALLOC_D #define AMALLOC_D #include "config.h" #ifdef USE_AMALLOC extern void *amalloc(int); extern void *acalloc(int,int); extern void *arealloc(void*,int); extern void afree(void*); extern void adump(); #define malloc amalloc #define calloc acalloc #define realloc arealloc #define free afree #else #define adump() (void)1 #endif #endif/*AMALLOC_D*/ discount-2.1.7/basename.c000066400000000000000000000015731222516442300152770ustar00rootroot00000000000000/* * mkdio -- markdown front end input functions * * Copyright (C) 2007 David L Parsons. * The redistribution terms are provided in the COPYRIGHT file that must * be distributed with this source code. */ #include "config.h" #include #include #include #include "mkdio.h" #include "cstring.h" #include "amalloc.h" static char * e_basename(const char *string, const int size, void *context) { char *ret; char *base = (char*)context; if ( base && string && (*string == '/') && (ret=malloc(strlen(base)+size+2)) ) { strcpy(ret, base); strncat(ret, string, size); return ret; } return 0; } static void e_free(char *string, void *context) { if ( string ) free(string); } void mkd_basename(MMIOT *document, char *base) { mkd_e_url(document, e_basename); mkd_e_data(document, base); mkd_e_free(document, e_free); } discount-2.1.7/configure.inc000077500000000000000000001036441222516442300160410ustar00rootroot00000000000000# @(#) configure.inc 1.42@(#) # Copyright (c) 1999-2007 David Parsons. All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # 3. My name may not be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY DAVID PARSONS ``AS IS'' AND ANY # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, # THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A # PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DAVID # PARSONS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED # TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING # IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF # THE POSSIBILITY OF SUCH DAMAGE. # # # this preamble code is executed when this file is sourced and it picks # interesting things off the command line. # ac_default_path="/sbin:/usr/sbin:/bin:/usr/bin:/usr/local/bin:/usr/X11R6/bin" ac_standard="--src=DIR where the source lives (.) --prefix=DIR where to install the final product (/usr/local) --execdir=DIR where to put executables (prefix/bin) --sbindir=DIR where to put static executables (prefix/sbin) --confdir=DIR where to put configuration information (/etc) --libdir=DIR where to put libraries (prefix/lib) --libexecdir=DIR where to put private executables --mandir=DIR where to put manpages" __fail=exit if dirname B/A 2>/dev/null >/dev/null; then __ac_dirname() { dirname "$1" } else __ac_dirname() { echo "$1" | sed -e 's:/[^/]*$::' } fi __remove() { if [ \( -x "$1" \) -a "$__MACOS_DSYM" ]; then rm -rf "$1".dSYM fi rm -f "$@" } ac_progname=$0 ac_configure_command= Q=\' for x in "$@"; do ac_configure_command="$ac_configure_command $Q$x$Q" done # ac_configure_command="$*" __d=`__ac_dirname "$ac_progname"` if [ "$__d" = "$ac_progname" ]; then AC_SRCDIR=`pwd` else AC_SRCDIR=`cd $__d;pwd` fi __ac_dir() { if test -d "$1"; then (cd "$1";pwd) else echo "$1"; fi } # # echo w/o newline # echononl() { ${ac_echo:-echo} "${@}$ac_echo_nonl" } # # log something to the terminal and to a logfile. # LOG () { echo "$@" echo "$@" 1>&5 } # # log something to the terminal without a newline, and to a logfile with # a newline # LOGN () { echononl "$@" 1>&5 echo "$@" } # # log something to the terminal # TLOG () { echo "$@" 1>&5 } # # log something to the terminal, no newline # TLOGN () { echononl "$@" 1>&5 } # # AC_CONTINUE tells configure not to bomb if something fails, but to # continue blithely along # AC_CONTINUE () { __fail="return" } # # generate a .o file from sources # __MAKEDOTO() { AC_PROG_CC if $AC_CC -c -o ngc$$.o "$@" $AC_LIBS 2>ngc$$.err; then __remove ngc$$.o ngc$$.err TLOG " (found)" return 0 fi __remove ngc$$.o TLOG " (not found)" echo "test failed: command was $AC_CC -c -o ngc$$.o" "$@" $AC_LIBS echo "output:" cat ngc$$.err __remove ngc$$.err echo "offending sources:" for x in "$@"; do echo "$x:" cat $x done return 1 } # # Emulate gnu autoconf's AC_CHECK_HEADERS() function # AC_CHECK_HEADERS () { echo "/* AC_CHECK_HEADERS */" > ngc$$.c for hdr in $*; do echo "#include <$hdr>" >> ngc$$.c done echo "main() { }" >> ngc$$.c LOGN "looking for header $hdr" if __MAKEDOTO ngc$$.c; then AC_DEFINE 'HAVE_'`echo $hdr | $AC_UPPERCASE | tr './' '_'` 1 rc=0 else rc=1 fi __remove ngc$$.c return $rc } # # emulate GNU autoconf's AC_CHECK_FUNCS function # AC_CHECK_FUNCS () { AC_PROG_CC B=`echo "$1" | sed -e 's/(.*)//'` case "$B" in "$1") F="$1()"; need_proto=1 ;; *) F="$1" ; unset need_proto ;; esac shift __remove ngc$$.c while [ "$1" ]; do echo "#include <$1>" >> ngc$$.c shift done if [ "$need_proto" ]; then echo "void $F;" >> ngc$$.c fi cat >> ngc$$.c << EOF main() { $F; } EOF LOGN "looking for the $B function" if $AC_CC -o ngc$$ ngc$$.c $LIBS; then AC_DEFINE `echo ${2:-HAVE_$B} | $AC_UPPERCASE` 1 TLOG " (found)" rc=0 else echo "offending command was:" cat ngc$$.c echo "$AC_CC -o ngc$$ ngc$$.c $LIBS" TLOG " (not found)" rc=1 fi __remove ngc$$ ngc$$.c return $rc } # # check to see if some structure exists # # usage: AC_CHECK_STRUCT structure {include ...} # AC_CHECK_STRUCT () { struct=$1 shift __remove ngc$$.c for include in $*; do echo "#include <$include>" >> ngc$$.c done cat >> ngc$$.c << EOF main() { struct $struct foo; } EOF LOGN "looking for struct $struct" if __MAKEDOTO ngc$$.c; then AC_DEFINE HAVE_STRUCT_`echo ${struct} | $AC_UPPERCASE` rc=0 else rc=1 fi __remove ngc$$.c return $rc } # # check to see if some type exists # # usage: AC_CHECK_TYPE type {include ...} # AC_CHECK_TYPE () { type=$1 shift __remove ngc$$.c for include in $*; do echo "#include <$include>" >> ngc$$.c done cat >> ngc$$.c << EOF main() { $type foo; } EOF LOGN "looking for $type type" if __MAKEDOTO ngc$$.c; then AC_DEFINE HAVE_TYPE_`echo ${type} | $AC_UPPERCASE` rc=0 else rc=1 fi __remove ngc$$.c return $rc } # # check to see if some structure contains a field # # usage: AC_CHECK_FIELD structure field {include ...} # AC_CHECK_FIELD () { struct=$1 field=$2 shift 2 __remove ngc$$.c for include in $*;do echo "#include <$include>" >> ngc$$.c done cat >> ngc$$.c << EOF main() { struct $struct foo; foo.$field; } EOF LOGN "checking that struct $struct has a $field field" if __MAKEDOTO ngc$$.c; then AC_DEFINE HAVE_`echo ${struct}_$field | $AC_UPPERCASE` rc=0 else rc=1 fi __remove ngc$$.c return $rc } # # check that the C compiler works # AC_PROG_CC () { test "$AC_CC" && return 0 cat > ngc$$.c << \EOF #include main() { puts("hello, sailor"); } EOF TLOGN "checking the C compiler" unset AC_CFLAGS AC_LDFLAGS if [ "$CC" ] ; then AC_CC="$CC" elif [ "$WITH_PATH" ]; then AC_CC=`acLookFor cc` elif [ "`acLookFor cc`" ]; then # don't specify the full path if the user is looking in their $PATH # for a C compiler. AC_CC=cc fi # finally check for POSIX c89 test "$AC_CC" || AC_CC=`acLookFor c89` if [ ! "$AC_CC" ]; then TLOG " (no C compiler found)" $__fail 1 fi echo "checking out the C compiler" unset __MACOS_DSYM $AC_CC -o ngc$$ ngc$$.c status=$? test -d ngc$$.dSYM && __MACOS_DSYM=1 TLOGN " ($AC_CC)" if [ $status -eq 0 ]; then if $AC_CC -x c /dev/null -dM -E 2>&1 | grep '__clang__' >/dev/null; then TLOG " yuck, you're using clang" IS_CLANG=T IS_BROKEN_CC=T elif $AC_CC -v 2>&1 | grep 'gcc version' >/dev/null; then TLOG " oh ick, it looks like gcc" IS_GCC=T IS_BROKEN_CC=T else TLOG " ok" fi # check that the CFLAGS and LDFLAGS aren't bogus unset AC_CFLAGS AC_LDFLAGS if [ "$CFLAGS" ]; then test "$CFLAGS" && echo "validating CFLAGS=${CFLAGS}" if $AC_CC $CFLAGS -o ngc$$.o ngc$$.c ; then AC_CFLAGS=${CFLAGS:-"-g"} test "$CFLAGS" && echo "CFLAGS=\"${CFLAGS}\" are okay" elif [ "$CFLAGS" ]; then echo "ignoring bogus CFLAGS=\"${CFLAGS}\"" fi else AC_CFLAGS=-g fi if [ "$LDFLAGS" ]; then test "$LDFLAGS" && echo "validating LDFLAGS=${LDFLAGS}" if $AC_CC $LDFLAGS -o ngc$$ ngc$$.o; then AC_LDFLAGS=${LDFLAGS:-"-g"} test "$LDFLAGS" && TLOG "LDFLAGS=\"${LDFLAGS}\" are okay" elif [ "$LDFLAGS" ]; then TLOG "ignoring bogus LDFLAGS=\"${LDFLAGS}\"" fi else AC_LDFLAGS=${CFLAGS:-"-g"} fi else AC_FAIL " does not compile code properly" fi __remove ngc$$ ngc$$.c ngc$$.o return $status } # # acLookFor actually looks for a program, without setting anything. # acLookFor () { path=${AC_PATH:-$ac_default_path} case "X$1" in X-[rx]) __mode=$1 shift ;; *) __mode=-x ;; esac oldifs="$IFS" for program in $*; do IFS=":" for x in $path; do if [ $__mode $x/$program -a -f $x/$program ]; then echo $x/$program break 2 fi done done IFS="$oldifs" unset __mode } # # check that a program exists and set its path # MF_PATH_INCLUDE () { SYM=$1; shift case X$1 in X-[rx]) __mode=$1 shift ;; *) unset __mode ;; esac TLOGN "looking for $1" DEST=`acLookFor $__mode $*` __sym=`echo "$SYM" | $AC_UPPERCASE` if [ "$DEST" ]; then TLOG " ($DEST)" echo "$1 is $DEST" AC_MAK $SYM AC_DEFINE PATH_$__sym \""$DEST"\" AC_SUB $__sym "$DEST" eval CF_$SYM=$DEST return 0 else #AC_SUB $__sym '' echo "$1 is not found" TLOG " (not found)" return 1 fi } # # AC_INIT starts the ball rolling # # After AC_INIT, fd's 1 and 2 point to config.log # and fd 5 points to what used to be fd 1 # AC_INIT () { __config_files="config.cmd config.sub config.h config.mak config.log" rm -f $__config_files __cwd=`pwd` exec 5>&1 1>$__cwd/config.log 2>&1 AC_CONFIGURE_FOR=__AC_`echo $1 | sed -e 's/\..$//' | $AC_UPPERCASE | tr ' ' '_'`_D # check to see whether to use echo -n or echo ...\c # echo -n hello > $$ echo world >> $$ if grep "helloworld" $$ >/dev/null; then ac_echo="echo -n" echo "[echo -n] works" else ac_echo="echo" echo 'hello\c' > $$ echo 'world' >> $$ if grep "helloworld" $$ >/dev/null; then ac_echo_nonl='\c' echo "[echo ...\\c] works" fi fi rm -f $$ LOG "Configuring for [$1]" cat > $__cwd/config.h << EOF /* * configuration for $1${2:+" ($2)"}, generated `date` * by ${LOGNAME:-`whoami`}@`hostname` */ #ifndef $AC_CONFIGURE_FOR #define $AC_CONFIGURE_FOR 1 EOF unset __share if [ -d $AC_PREFIX/share/man ]; then for t in 1 2 3 4 5 6 7 8 9; do if [ -d $AC_PREFIX/share/man/man$t ]; then __share=/share elif [ -d $AC_PREFIX/share/man/cat$t ]; then __share=/share fi done else __share= fi if [ -d $AC_PREFIX/libexec ]; then __libexec=libexec else __libexec=lib fi AC_PREFIX=${AC_PREFIX:-/usr/local} AC_EXECDIR=${AC_EXECDIR:-$AC_PREFIX/bin} AC_SBINDIR=${AC_SBINDIR:-$AC_PREFIX/sbin} AC_LIBDIR=${AC_LIBDIR:-$AC_PREFIX/lib} AC_MANDIR=${AC_MANDIR:-$AC_PREFIX$__share/man} AC_LIBEXEC=${AC_LIBEXEC:-$AC_PREFIX/$__libexec} AC_CONFDIR=${AC_CONFDIR:-/etc} AC_PATH=${WITH_PATH:-$PATH} AC_PROG_CPP AC_PROG_INSTALL ac_os=`uname -s` _os=`echo $ac_os | $AC_UPPERCASE | sed -e 's/[^A-Z0-9_].*$//'` AC_DEFINE OS_$_os 1 eval OS_${_os}=1 unset _os } # # AC_LIBRARY checks to see if a given library exists and contains the # given function. # usage: AC_LIBRARY function library [alternate ...] # AC_LIBRARY() { SRC=$1 shift __acllibs= __aclhdrs= for x in "$@"; do case X"$x" in X-l*) __acllibs="$__acllibs $x" ;; *) __aclhdrs="$__aclhdrs $x" ;; esac done # first see if the function can be found in any of the # current libraries AC_QUIET AC_CHECK_FUNCS $SRC $__aclhdrs && return 0 # then search through the list of libraries __libs="$LIBS" for x in $__acllibs; do LIBS="$__libs $x" if AC_QUIET AC_CHECK_FUNCS $SRC $__aclhdrs; then AC_LIBS="$AC_LIBS $x" return 0 fi done return 1 } # # AC_PROG_LEX checks to see if LEX exists, and if it's lex or flex. # AC_PROG_LEX() { TLOGN "looking for lex " DEST=`acLookFor lex` if [ "$DEST" ]; then AC_MAK LEX AC_DEFINE PATH_LEX \"$DEST\" AC_SUB 'LEX' "$DEST" echo "lex is $DEST" else DEST=`acLookFor flex` if [ "$DEST" ]; then AC_MAK FLEX AC_DEFINE 'LEX' \"$DEST\" AC_SUB 'LEX', "$DEST" echo "lex is $DEST" else AC_SUB LEX '' echo "neither lex or flex found" TLOG " (not found)" return 1 fi fi if AC_LIBRARY yywrap -ll -lfl; then TLOG "($DEST)" return 0 fi TLOG "(no lex library found)" return 1 } # # AC_PROG_YACC checks to see if YACC exists, and if it's bison or # not. # AC_PROG_YACC () { TLOGN "looking for yacc " DEST=`acLookFor yacc` if [ "$DEST" ]; then AC_MAK YACC AC_DEFINE PATH_YACC \"$DEST\" AC_SUB 'YACC' "$DEST" TLOG "($DEST)" echo "yacc is $DEST" else DEST=`acLookFor bison` if [ "$DEST" ]; then AC_MAK BISON AC_DEFINE 'YACC' \"$DEST\" AC_SUB 'YACC' "$DEST -y" echo "yacc is $DEST -y" TLOG "($DEST -y)" else AC_SUB 'YACC' '' echo "neither yacc or bison found" TLOG " (not found)" return 1 fi fi return 0 } # # AC_PROG looks for a program # AC_PROG () { PN=`basename $1 | $AC_UPPERCASE | tr -dc $AC_UPPER_PAT` if set | grep -v PROG_$PN >/dev/null; then TLOGN "looking for $1" DEST=`acLookFor $1` if [ "$DEST" ]; then eval PROG_$PN="$DEST" AC_SUB $PN $DEST TLOG " ($DEST)" return 0 fi AC_SUB $PN true TLOG " (not found)" return 1 fi } # # AC_PROG_LN_S checks to see if ln exists, and, if so, if ln -s works # AC_PROG_LN_S () { test "$AC_FIND_PROG" || AC_PROG_FIND test "$AC_FIND_PROG" || return 1 TLOGN "looking for \"ln -s\"" DEST=`acLookFor ln` if [ "$DEST" ]; then rm -f /tmp/b$$ $DEST -s /tmp/a$$ /tmp/b$$ if [ "`$AC_FIND_PROG /tmp/b$$ -type l -print`" ]; then TLOG " ($DEST)" echo "$DEST exists, and ln -s works" PROG_LN_S="$DEST -s" AC_SUB 'LN_S' "$DEST -s" rm -f /tmp/b$$ else AC_SUB 'LN_S' '' TLOG " ($DEST exists, but -s does not seem to work)" echo "$DEST exists, but ln -s doesn't seem to work" rm -f /tmp/b$$ return 1 fi else AC_SUB 'LN_S' '' echo "ln not found" TLOG " (not found)" return 1 fi } # # AC_PROG_FIND looks for the find program and sets the FIND environment # variable # AC_PROG_FIND () { if test -z "$AC_FIND_PROG"; then MF_PATH_INCLUDE FIND find rc=$? AC_FIND_PROG=$DEST return $rc fi return 0 } # # AC_PROG_AWK looks for the awk program and sets the AWK environment # variable # AC_PROG_AWK () { if test -z "$AC_AWK_PROG"; then MF_PATH_INCLUDE AWK awk rc=$? AC_AWK_PROG=$DEST return $rc fi return 0 } # # AC_PROG_SED looks for the sed program and sets the SED environment # variable # AC_PROG_SED () { if test -z "$AC_SED_PROG"; then MF_PATH_INCLUDE SED sed rc=$? AC_SED_PROG=$DEST return $rc fi return 0 } # # AC_HEADER_SYS_WAIT looks for sys/wait.h # AC_HEADER_SYS_WAIT () { AC_CHECK_HEADERS sys/wait.h || return 1 } # # AC_TYPE_PID_T checks to see if the pid_t type exists # AC_TYPE_PID_T () { AC_CHECK_TYPE pid_t sys/types.h return $? } # # AC_C_CONST checks to see if the compiler supports the const keyword # AC_C_CONST () { cat > ngc$$.c << EOF const char me=1; EOF LOGN "checking for \"const\" keyword" if __MAKEDOTO ngc$$.c; then rc=0 else AC_DEFINE 'const' '/**/' rc=1 fi __remove ngc$$.c return $rc } # # AC_C_VOLATILE checks to see if the compiler supports the volatile keyword # AC_C_VOLATILE () { echo 'f() { volatile char me=1; }' > ngc$$.c LOGN "checking for \"volatile\" keyword" if __MAKEDOTO ngc$$.c; then rc=0 else AC_DEFINE 'volatile' '/**/' rc=1 fi __remove ngc$$.c return $rc } # # AC_C_INLINE checks to see if compiler supports the inline keyword # AC_C_INLINE() { echo 'inline int foo() { return 1; }' > ngc$$.c LOGN 'Checking for "inline" keyword' if __MAKEDOTO ngc$$.c; then rc=0 else AC_DEFINE inline '/**/' rc=1 fi __remove ngc$$.c return $rc } # # AC_SCALAR_TYPES checks to see if the compiler can generate 2 and 4 byte ints. # AC_SCALAR_TYPES () { rc=1 LOGN "defining WORD & DWORD scalar types" if AC_QUIET AC_CHECK_HEADERS WinDef.h; then # windows machine; BYTE, WORD, DWORD already # defined echo "#include " >> $__cwd/config.h TLOG " (defined in WinDef.h)" return 0 fi cat > ngc$$.c << EOF #include #include int pound_define = 1; void say(char *w, char *v) { printf(pound_define ? "#define %s %s\n" : "s:@%s@:%s:g\n", w, v); } main(argc, argv) char **argv; { unsigned long v_long; unsigned int v_int; unsigned short v_short; if ( argc > 1 && strcmp(argv[1], "sub") == 0 ) pound_define = 0; if (sizeof v_long == 4) say("DWORD", "unsigned long"); else if (sizeof v_int == 4) say("DWORD", "unsigned int"); else exit(1); if (sizeof v_int == 2) say("WORD", "unsigned int"); else if (sizeof v_short == 2) say("WORD", "unsigned short"); else exit(2); say("BYTE", "unsigned char"); exit(0); } EOF if $AC_CC ngc$$.c -o ngc$$; then while [ "$1" ]; do case "$1" in sub)if ./ngc$$ sub >> $__cwd/config.sub; then rc=0 fi;; *) if ./ngc$$ >> $__cwd/config.h; then rc=0 fi ;; esac shift done if [ "$rc" != 0 ]; then if ./ngc$$ >> $__cwd/config.h; then rc=1 fi fi fi __remove ngc$$ ngc$$.c case "$rc" in 0) TLOG "" ;; *) AC_FAIL " ** FAILED **" ;; esac return $rc } # # AC_OUTPUT generates makefiles from makefile.in's # AC_OUTPUT () { cd $__cwd AC_SUB 'LIBS' "$AC_LIBS" AC_SUB 'CONFIGURE_FILES' "$__config_files" AC_SUB 'GENERATED_FILES' "$*" AC_SUB 'CC' "$AC_CC" AC_SUB 'CFLAGS' "$AC_CFLAGS" AC_SUB 'LDFLAGS' "$AC_LDFLAGS" AC_SUB 'srcdir' "$AC_SRCDIR" AC_SUB 'prefix' "$AC_PREFIX" AC_SUB 'exedir' "$AC_EXECDIR" AC_SUB 'sbindir' "$AC_SBINDIR" AC_SUB 'libdir' "$AC_LIBDIR" AC_SUB 'libexec' "$AC_LIBEXEC" AC_SUB 'confdir' "$AC_CONFDIR" AC_SUB 'mandir' "$AC_MANDIR" if echo "$__config_files" | grep -v librarian.sh >/dev/null; then # write a librarian that works with static libraries if AC_PROG_LN_S ; then __dolink=$PROG_LN_S elif AC_PROG ln; then __dolink=$PROG_LN elif AC_PROG cp; then __dolink=$PROG_CP else __dolink=: fi AC_PROG ar AC_PROG ranlib AC_SUB LD_LIBRARY_PATH HERE AC __config_files="$__config_files librarian.sh" cat > librarian.sh << EOF #! /bin/sh # # Build static libraries, hiding (some) ickiness from the makefile ACTION=\$1; shift LIBRARY=\$1; shift VERSION=\$1; shift case "\$ACTION" in make) ${PROG_AR} crv \$LIBRARY.a "\$@" ${PROG_RANLIB} \$LIBRARY.a rm -f \$LIBRARY ${__dolink} \$LIBRARY.a \$LIBRARY ;; files) echo "\${LIBRARY}.a" ;; install)$PROG_INSTALL -m 644 \${LIBRARY}.a \$1 ;; esac EOF fi chmod +x librarian.sh if [ -r config.sub ]; then test "$AC_SED_PROG" || AC_PROG_SED test "$AC_SED_PROG" || return 1 echo >> config.h echo "#endif/* ${AC_CONFIGURE_FOR} */" >> config.h rm -f config.cmd Q=\' cat - > config.cmd << EOF #! /bin/sh ${CC:+CC=${Q}${CC}${Q}} ${CFLAGS:+CFLAGS=${Q}${CFLAGS}${Q}} $ac_progname $ac_configure_command EOF chmod +x config.cmd __d=$AC_SRCDIR for makefile in $*;do if test -r $__d/${makefile}.in; then LOG "generating $makefile" ./config.md `__ac_dirname ./$makefile` 2>/dev/null $AC_SED_PROG -f config.sub < $__d/${makefile}.in > $makefile __config_files="$__config_files $makefile" else LOG "WARNING: ${makefile}.in does not exist!" fi done unset __d else echo fi } # # AC_CHECK_FLOCK checks to see if flock() exists and if the LOCK_NB argument # works properly. # AC_CHECK_FLOCK() { AC_CHECK_HEADERS sys/types.h sys/file.h fcntl.h cat << EOF > ngc$$.c #include #include #include #include main() { int x = open("$$.c", O_RDWR, 0666); int y = open("$$.c", O_RDWR, 0666); if (flock(x, LOCK_EX) != 0) exit(1); if (flock(y, LOCK_EX|LOCK_NB) == 0) exit(1); exit(0); } EOF LOGN "checking flock() sanity" HAS_FLOCK=0 if $AC_CC -o ngc$$ ngc$$.c ; then if ./flock ; then LOG " (good)" HAS_FLOCK=1 AC_DEFINE HAS_FLOCK else LOG " (bad)" fi else LOG " (not found)" fi __remove ngc$$ ngc$$.c case "$HAS_FLOCK" in 0) return 1 ;; *) return 0 ;; esac } # # AC_CHECK_RESOLVER finds out whether the berkeley resolver is # present on this system. # AC_CHECK_RESOLVER () { AC_PROG_CC TLOGN "looking for the Berkeley resolver library" __ACR_rc=0 cat > ngc$$.c << EOF #include #include #include #include main() { char bfr[256]; res_init(); res_query("hello", C_IN, T_A, bfr, sizeof bfr); } EOF if $AC_CC -o ngc$$ ngc$$.c; then TLOG " (found)" elif $AC_CC -o ngc$$ ngc$$.c -lresolv; then TLOG " (found, needs -lresolv)" AC_LIBS="$AC_LIBS -lresolv" elif $AC_CC -DBIND_8_COMPAT -o ngc$$ ngc$$.c; then TLOG " (found, needs BIND_8_COMPAT)" AC_DEFINE BIND_8_COMPAT 1 elif $AC_CC -DBIND_8_COMPAT -o ngc$$ ngc$$.c -lresolv; then TLOG " (found, needs BIND_8_COMPAT & -lresolv)" AC_DEFINE BIND_8_COMPAT 1 else TLOG " (not found)" __ACR_rc=1 fi __remove ngc$$ ngc$$.c return $__ACR_rc } # # AC_CHECK_ALLOCA looks for alloca # AC_CHECK_ALLOCA () { AC_PROG_CC AC_CHECK_HEADERS stdlib.h cat - > ngc$$.c << EOF #if T # include #else # include #endif main() { alloca(10); } EOF LOGN "looking for the alloca function" if $AC_CC -DT ngc$$.c -o ngc$$; then AC_DEFINE 'HAVE_ALLOCA_H' 1 status=0 TLOG " (found in alloca.h)" elif $AC_CC ngc$$.c -o ngc$$; then TLOG " (found)" status=0 else TLOG " (not found)" status=1 fi __remove ngc$$ ngc$$.c return $status } # # AC_CHECK_BASENAME looks for a copy of basename that does NOT use # a local static buffer to hold results in. # AC_CHECK_BASENAME() { TLOGN "looking for a reentrant basename " cat > ngc$$.c << EOF #include extern char *basename(char*); main() { char *a = basename("/a/test"); char *b = basename("/a/nother"); return (strcmp(a,b) != 0) ? 0 : 1; } EOF if $AC_CC -o ngc$$ ngc$$.c $LIBS; then if ./ngc$$; then TLOG "(found)" AC_DEFINE 'HAVE_BASENAME' 1 AC_CHECK_HEADERS libgen.h else TLOG "(broken)" fi else TLOG "(not found)" fi __remove ngc$$ ngc$$.c } # # AC_COMPILER_PIC checks for the compiler option to produce position independent # code. At the moment we assume gcc semantics. # AC_COMPILER_PIC () { AC_PROG_CC LOGN "checking for C compiler option to produce PIC " echo "int some_variable = 0;" > ngc$$.c if $AC_CC -c -fPIC -o ngc$$ ngc$$.c $LIBS; then AC_CFLAGS="$AC_CFLAGS -fPIC" LOG "(-fPIC)" __rc=0 else LOG "(none)" __rc=1 fi __remove ngc$$ ngc$$.c return $__rc } # generate a macosX librarian # __AC_MACOS_LIBRARIAN() { AC_SUB LD_LIBRARY_PATH DYLD_LIBRARY_PATH __config_files="$__config_files librarian.sh" cat > librarian.sh << EOF #! /bin/sh # # Build MacOS shared libraries, hiding (some) ickiness from the makefile ACTION=\$1; shift LIBRARY=\$1; shift eval \`awk -F. '{ printf "MAJOR=%d\n", \$1; printf "VERSION=%d.%d.%d\n", \$1, \$2, \$3; }' \$1\` shift LIBNAME=\$LIBRARY.dylib FULLNAME=\$LIBNAME case "\$ACTION" in make) FLAGS="$AC_CFLAGS -dynamiclib" VFLAGS="-current_version \$VERSION -compatibility_version \$MAJOR" rm -f \$LIBRARY if $AC_CC \$FLAGS \$VFLAGS -o \$FULLNAME "\$@"; then $PROG_LN_S \$FULLNAME \$LIBRARY fi ;; files) echo "\$FULLNAME" ;; install)$PROG_INSTALL -c \$FULLNAME "\$1" ;; esac EOF chmod +x librarian.sh } # Generate an ELF librarian (for Linux, freebsd) # __AC_ELF_LIBRARIAN() { AC_SUB LD_LIBRARY_PATH LD_LIBRARY_PATH # -Wl option probably works, but be paranoid anyway _VFLAGS="$AC_PICFLAG -shared -Wl,-soname,ngc$$.so.1" if $AC_CC $_VFLAGS -o ngc$$.so ngc$$.c; then USE_SONAME=T fi LDCONFIG=`AC_PATH=/sbin:/usr/sbin:/usr/local/sbin acLookFor ldconfig` __config_files="$__config_files librarian.sh" cat > librarian.sh << EOF #! /bin/sh # # Build ELF shared libraries, hiding (some) ickiness from the makefile ACTION=\$1; shift LIBRARY=\$1; shift eval \`awk -F. '{ printf "MAJOR=%d\n", \$1; printf "VERSION=%d.%d.%d\n", \$1, \$2, \$3; }' \$1\` shift LIBNAME=\$LIBRARY.so FULLNAME=\$LIBNAME.\$VERSION case "\$ACTION" in make) FLAGS="$AC_CFLAGS -shared" unset VFLAGS test "$USE_SONAME" && VFLAGS="-Wl,-soname,\$LIBNAME.\$MAJOR" rm -f \$LIBRARY \$LIBNAME \$LIBNAME.\$MAJOR if $AC_CC \$FLAGS \$VFLAGS -o \$FULLNAME "\$@"; then $PROG_LN_S \$FULLNAME \$LIBRARY $PROG_LN_S \$FULLNAME \$LIBNAME $PROG_LN_S \$FULLNAME \$LIBNAME.\$MAJOR fi ;; files) echo "\$FULLNAME" "\$LIBNAME" "\$LIBNAME.\$MAJOR" ;; install)$PROG_INSTALL -c \$FULLNAME "\$1" $PROG_LN_S -f \$FULLNAME \$1/\$LIBNAME.\$MAJOR $PROG_LN_S -f \$FULLNAME \$1/\$LIBNAME test "$LDCONFIG" && $LDCONFIG "\$1" ;; esac EOF chmod +x librarian.sh } # # AC_CC_SHLIBS checks if the C compiler can produce shared libraries # and if it can writes a librarian that handles those libraries for us. # AC_CC_SHLIBS () { AC_PROG_CC || AC_FAIL "Need a C compiler to build shared libraries" AC_PROG_LN_S || AC_FAIL "Need to be able to make symbolic links for shared libraries" AC_PROG_INSTALL || AC_FAIL "Need an install program to install shared libraries" LOGN "checking whether the C compiler can build shared libraries " echo "int some_variable = 0;" > ngc$$.c if uname -a | grep Darwin >/dev/null; then # Claims to be macos? if $AC_CC $AC_PICFLAG -dynamiclib -o ngc$$.so ngc$$.c; then __AC_MACOS_LIBRARIAN LOG "(yes; macos dylib)" __rc=0 else LOG "(no)" __rc=1 fi elif $AC_CC $AC_PICFLAG -shared -o ngc$$.so ngc$$.c; then __AC_ELF_LIBRARIAN LOG "(yes; -shared)" __rc=0 else LOG "(no)" __rc=1 fi __remove ngc$$.so ngc$$.c return $__rc } # # AC_PROG_INSTALL finds the install program and guesses whether it's a # Berkeley or GNU install program # AC_PROG_INSTALL () { DEST=`acLookFor install` LOGN "looking for install" unset IS_BSD if [ "$DEST" ]; then # BSD install or GNU install? Let's find out... touch /tmp/a$$ $DEST /tmp/a$$ /tmp/b$$ if test -r /tmp/a$$; then LOG " ($DEST)" else IS_BSD=1 LOG " ($DEST) bsd install" fi rm -f /tmp/a$$ /tmp/b$$ else DEST=`acLookFor ginstall` if [ "$DEST" ]; then LOG " ($DEST)" else DEST="false" LOG " (not found)" fi fi if [ "$IS_BSD" ]; then PROG_INSTALL="$DEST -c" else PROG_INSTALL="$DEST" fi AC_SUB 'INSTALL' "$PROG_INSTALL" AC_SUB 'INSTALL_PROGRAM' "$PROG_INSTALL -s -m 755" AC_SUB 'INSTALL_DATA' "$PROG_INSTALL -m 444" # finally build a little directory installer # if mkdir -p works, use that, otherwise use install -d, # otherwise build a script to do it by hand. # in every case, test to see if the directory exists before # making it. if mkdir -p $$a/b; then # I like this method best. __mkdir="mkdir -p" rmdir $$a/b rmdir $$a elif $PROG_INSTALL -d $$a/b; then __mkdir="$PROG_INSTALL -d" rmdir $$a/b rmdir $$a fi __config_files="$__config_files config.md" AC_SUB 'INSTALL_DIR' "$__cwd/config.md" echo "#! /bin/sh" > $__cwd/config.md echo "# script generated" `date` "by configure.sh" >> $__cwd/config.md echo >> $__cwd/config.md if [ "$__mkdir" ]; then echo "test -d \"\$1\" || $__mkdir \"\$1\"" >> $__cwd/config.md echo "exit $?" >> $__cwd/config.md else cat - >> $__cwd/config.md << \EOD pieces=`IFS=/; for x in $1; do echo $x; done` dir= for x in $pieces; do dir="$dir$x" mkdir $dir || exit 1 dir="$dir/" done exit 0 EOD fi chmod +x $__cwd/config.md } # # acCheckCPP is a local that runs a C preprocessor with a given set of # compiler options # acCheckCPP () { cat > ngc$$.c << EOF #define FOO BAR FOO EOF if $1 $2 ngc$$.c > ngc$$.o; then if grep -v '#define' ngc$$.o | grep -s BAR >/dev/null; then echo "CPP=[$1], CPPFLAGS=[$2]" AC_SUB 'CPP' "$1" AC_SUB 'CPPFLAGS' "$2" rm ngc$$.c ngc$$.o return 0 fi fi rm ngc$$.c ngc$$.o return 1 } # # AC_PROG_CPP checks for cpp, then checks to see which CPPFLAGS are needed # to run it as a filter. # AC_PROG_CPP () { if [ "$AC_CPP_PROG" ]; then DEST=$AC_CPP_PROG else __ac_path="$AC_PATH" AC_PATH="/lib:/usr/lib:${__ac_path:-$ac_default_path}" DEST=`acLookFor cpp` AC_PATH="$__ac_path" fi unset fail LOGN "Looking for cpp" if [ "$DEST" ]; then TLOGN " ($DEST)" acCheckCPP $DEST "$CPPFLAGS" || \ acCheckCPP $DEST -traditional-cpp -E || \ acCheckCPP $DEST -E || \ acCheckCPP $DEST -traditional-cpp -pipe || \ acCheckCPP $DEST -pipe || fail=1 if [ "$fail" ]; then AC_FAIL " (can't run cpp as a pipeline)" else TLOG " ok" return 0 fi fi AC_FAIL " (not found)" } # # AC_FAIL spits out an error message, then __fail's AC_FAIL() { LOG "$*" $__fail 1 } # # AC_SUB writes a substitution into config.sub AC_SUB() { ( _subst=`echo $2 | sed -e 's/;/\\;/g'` echo "s;@$1@;$_subst;g" ) >> $__cwd/config.sub } # # AC_MAK writes a define into config.mak AC_MAK() { echo "HAVE_$1 = 1" >> $__cwd/config.mak } # # AC_DEFINE adds a #define to config.h AC_DEFINE() { echo "#define $1 ${2:-1}" >> $__cwd/config.h } # # AC_INCLUDE adds a #include to config.h AC_INCLUDE() { echo "#include \"$1\"" >> $__cwd/config.h } # # AC_CONFIG adds a configuration setting to all the config files AC_CONFIG() { AC_DEFINE "PATH_$1" \""$2"\" AC_MAK "$1" AC_SUB "$1" "$2" } # # AC_QUIET does something quietly AC_QUIET() { eval $* 5>/dev/null } AC_TR=`acLookFor tr` if [ "$AC_TR" ]; then # try posix-style tr ABC=`echo abc | tr abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ` if [ "$ABC" = "ABC" ]; then AC_UPPERCASE="$AC_TR abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ" AC_UPPER_PAT="ABCDEFGHIJKLMNOPQRSTUVWXYZ" else ABC=`echo abc | tr a-z A-Z` if [ "$ABC" = "ABC" ]; then AC_UPPERCASE="$AC_TR a-z A-Z" AC_UPPER_PAT="A-Z" else ABC=`echo abc | tr '[a-z]' '[A-Z]'` if [ "$ABC" = "ABC" ]; then AC_UPPERCASE="$AC_TR '[a-z]' '[A-Z]'" AC_UPPER_PAT="'[A-Z]'" else AC_FAIL "$AC_TR cannot translate lowercase to uppercase" return 0 fi fi fi else AC_FAIL "configure requires a functional version of tr" fi while [ $# -gt 0 ]; do unset matched case X"$1" in X--src|X--srcdir) AC_SRCDIR=`__ac_dir "$2"` _set_srcdir=1 shift 2;; X--src=*|X--srcdir=*) __d=`echo "$1" | sed -e 's/^[^=]*=//'` AC_SRCDIR=`__ac_dir "$__d"` _set_srcdir=1 shift 1 ;; X--prefix) AC_PREFIX=`__ac_dir "$2"` _set_prefix=1 shift 2;; X--prefix=*) __d=`echo "$1"| sed -e 's/^[^=]*=//'` AC_PREFIX=`__ac_dir "$__d"` _set_prefix=1 shift 1;; X--confdir) AC_CONFDIR=`__ac_dir "$2"` _set_confdir=1 shift 2;; X--confdir=*) __d=`echo "$1" | sed -e 's/^[^=]*=//'` AC_CONFDIR=`__ac_dir "$__d"` _set_confdir=1 shift 1;; X--libexec|X--libexecdir) AC_LIBEXEC=`__ac_dir "$2"` _set_libexec=1 shift 2;; X--libexec=*|X--libexecdir=*) __d=`echo "$1" | sed -e 's/^[^=]*=//'` AC_LIBEXEC=`__ac_dir "$__d"` _set_libexec=1 shift 1;; X--lib|X--libdir) AC_LIBDIR=`__ac_dir "$2"` _set_libdir=1 shift 2;; X--lib=*|X--libdir=*) __d=`echo "$1" | sed -e 's/^[^=]*=//'` AC_LIBDIR=`__ac_dir "$__d"` _set_libdir=1 shift 1;; X--exec|X--execdir) AC_EXECDIR=`__ac_dir "$2"` _set_execdir=1 shift 2;; X--exec=*|X--execdir=*) __d=`echo "$1" | sed -e 's/^[^=]*=//'` AC_EXECDIR=`__ac_dir "$__d"` _set_execdir=1 shift 1;; X--sbin|X--sbindir) AC_SBINDIR=`__ac_dir "$2"` _set_sbindir=1 shift 2;; X--sbin=*|X--sbindir=*) __d=`echo "$1" | sed -e 's/^[^=]*=//'` AC_SBINDIR=`__ac_dir "$__d"` _set_sbindir=1 shift 1;; X--man|X--mandir) AC_MANDIR=`__ac_dir "$2"` _set_mandir=1 shift 2;; X--man=*|X--mandir=*) __d=`echo "$1" | sed -e 's/^[^=]*=//'` AC_MANDIR=`__ac_dir "$__d"` _set_mandir=1 shift 1;; X--use-*=*) _var=`echo "$1"| sed -n 's/^--use-\([A-Za-z][-A-Za-z0-9_]*\)=.*$/\1/p'` if [ "$_var" ]; then _val=`echo "$1" | sed -e 's/^--use-[^=]*=\(.*\)$/\1/'` _v=`echo $_var | $AC_UPPERCASE | tr '-' '_'` case X"$_val" in X[Yy][Ee][Ss]|X[Tt][Rr][Uu][Ee]) eval USE_${_v}=T ;; X[Nn][Oo]|X[Ff][Aa][Ll][Ss][Ee]) eval unset USE_${_v} ;; *) echo "Bad value for --use-$_var ; must be yes or no" exit 1 ;; esac else echo "Bad option $1. Use --help to show options" 1>&2 exit 1 fi shift 1 ;; X--use-*) _var=`echo "$1"|sed -n 's/^--use-\([A-Za-z][-A-Za-z0-9_]*\)$/\1/p'` _v=`echo $_var | $AC_UPPERCASE | tr '-' '_'` eval USE_${_v}=T shift 1;; X--with-*=*) _var=`echo "$1"| sed -n 's/^--with-\([A-Za-z][-A-Za-z0-9_]*\)=.*$/\1/p'` if [ "$_var" ]; then _val=`echo "$1" | sed -e 's/^--with-[^=]*=\(.*\)$/\1/'` _v=`echo $_var | $AC_UPPERCASE | tr '-' '_'` eval WITH_${_v}=\"$_val\" else echo "Bad option $1. Use --help to show options" 1>&2 exit 1 fi shift 1 ;; X--with-*) _var=`echo "$1" | sed -n 's/^--with-\([A-Za-z][A-Za-z0-9_-]*\)$/\1/p'` if [ "$_var" ]; then _v=`echo $_var | $AC_UPPERCASE | tr '-' '_'` eval WITH_${_v}=1 else echo "Bad option $1. Use --help to show options" 1>&2 exit 1 fi shift 1 ;; X--help) echo "$ac_standard" test "$ac_help" && echo "$ac_help" exit 0;; *) if [ "$LOCAL_AC_OPTIONS" ]; then eval "$LOCAL_AC_OPTIONS" else ac_error=T fi if [ "$ac_error" ]; then echo "Bad option $1. Use --help to show options" 1>&2 exit 1 fi ;; esac done discount-2.1.7/configure.sh000077500000000000000000000076161222516442300157040ustar00rootroot00000000000000#! /bin/sh # local options: ac_help is the help message that describes them # and LOCAL_AC_OPTIONS is the script that interprets them. LOCAL_AC_OPTIONS # is a script that's processed with eval, so you need to be very careful to # make certain that what you quote is what you want to quote. # load in the configuration file # ac_help='--enable-amalloc Enable memory allocation debugging --with-tabstops=N Set tabstops to N characters (default is 4) --with-dl=X Use Discount, Extra, or Both types of definition list --with-id-anchor Use id= anchors for table-of-contents links --with-github-tags Allow `_` and `-` in <> tags --with-fenced-code Allow fenced code blocks --enable-all-features Turn on all stable optional features --shared Build shared libraries (default is static)' LOCAL_AC_OPTIONS=' set=`locals $*`; if [ "$set" ]; then eval $set shift 1 else ac_error=T; fi' locals() { K=`echo $1 | $AC_UPPERCASE` case "$K" in --SHARED) echo TRY_SHARED=T ;; --ENABLE-ALL|--ENABLE-ALL-FEATURES) echo WITH_AMALLOC=T ;; --ENABLE-*) enable=`echo $K | sed -e 's/--ENABLE-//' | tr '-' '_'` echo WITH_${enable}=T ;; esac } TARGET=markdown . ./configure.inc AC_INIT $TARGET __DL=`echo "$WITH_DL" | $AC_UPPERCASE` case "$__DL" in EXTRA) AC_DEFINE 'USE_EXTRA_DL' 1 ;; DISCOUNT|1|"") AC_DEFINE 'USE_DISCOUNT_DL' 1 ;; BOTH) AC_DEFINE 'USE_EXTRA_DL' 1 AC_DEFINE 'USE_DISCOUNT_DL' 1 ;; *) AC_FAIL "Unknown value <$WITH_DL> for --with-dl (want 'discount', 'extra', or 'both')" ;; esac test "$WITH_FENCED_CODE" && AC_DEFINE "WITH_FENCED_CODE" 1 test "$WITH_ID_ANCHOR" && AC_DEFINE 'WITH_ID_ANCHOR' 1 test "$WITH_GITHUB_TAGS" && AC_DEFINE 'WITH_GITHUB_TAGS' 1 AC_PROG_CC test "$TRY_SHARED" && AC_COMPILER_PIC && AC_CC_SHLIBS if [ "IS_BROKEN_CC" ]; then case "$AC_CC $AC_CFLAGS" in *-pedantic*) ;; *) # hack around deficiencies in gcc and clang # AC_DEFINE 'while(x)' 'while( (x) != 0 )' AC_DEFINE 'if(x)' 'if( (x) != 0 )' if [ "$IS_CLANG" ]; then AC_CC="$AC_CC -Wno-implicit-int" elif [ "$IS_GCC" ]; then AC_CC="$AC_CC -Wno-return-type -Wno-implicit-int" fi ;; esac fi AC_PROG ar || AC_FAIL "$TARGET requires ar" AC_PROG ranlib AC_C_VOLATILE AC_C_CONST AC_C_INLINE AC_SCALAR_TYPES sub hdr AC_CHECK_BASENAME AC_CHECK_HEADERS sys/types.h pwd.h && AC_CHECK_FUNCS getpwuid if AC_CHECK_FUNCS srandom; then AC_DEFINE 'INITRNG(x)' 'srandom((unsigned int)x)' elif AC_CHECK_FUNCS srand; then AC_DEFINE 'INITRNG(x)' 'srand((unsigned int)x)' else AC_DEFINE 'INITRNG(x)' '(void)1' fi if AC_CHECK_FUNCS 'bzero((char*)0,0)'; then : # Yay elif AC_CHECK_FUNCS 'memset((char*)0,0,0)'; then AC_DEFINE 'bzero(p,s)' 'memset(p,s,0)' else AC_FAIL "$TARGET requires bzero or memset" fi if AC_CHECK_FUNCS random; then AC_DEFINE 'COINTOSS()' '(random()&1)' elif AC_CHECK_FUNCS rand; then AC_DEFINE 'COINTOSS()' '(rand()&1)' else AC_DEFINE 'COINTOSS()' '1' fi if AC_CHECK_FUNCS strcasecmp; then : elif AC_CHECK_FUNCS stricmp; then AC_DEFINE strcasecmp stricmp else AC_FAIL "$TARGET requires either strcasecmp() or stricmp()" fi if AC_CHECK_FUNCS strncasecmp; then : elif AC_CHECK_FUNCS strnicmp; then AC_DEFINE strncasecmp strnicmp else AC_FAIL "$TARGET requires either strncasecmp() or strnicmp()" fi if AC_CHECK_FUNCS fchdir || AC_CHECK_FUNCS getcwd ; then AC_SUB 'THEME' '' else AC_SUB 'THEME' '#' fi if [ -z "$WITH_TABSTOPS" ]; then TABSTOP=4 elif [ "$WITH_TABSTOPS" -eq 1 ]; then TABSTOP=8 else TABSTOP=$WITH_TABSTOPS fi AC_DEFINE 'TABSTOP' $TABSTOP AC_SUB 'TABSTOP' $TABSTOP if [ "$WITH_AMALLOC" ]; then AC_DEFINE 'USE_AMALLOC' 1 AC_SUB 'AMALLOC' 'amalloc.o' else AC_SUB 'AMALLOC' '' fi [ "$OS_FREEBSD" -o "$OS_DRAGONFLY" ] || AC_CHECK_HEADERS malloc.h [ "$WITH_PANDOC_HEADER" ] && AC_DEFINE 'PANDOC_HEADER' '1' AC_OUTPUT Makefile version.c mkdio.h discount-2.1.7/css.c000066400000000000000000000031411222516442300143050ustar00rootroot00000000000000/* markdown: a C implementation of John Gruber's Markdown markup language. * * Copyright (C) 2009 David 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 "config.h" #include "cstring.h" #include "markdown.h" #include "amalloc.h" /* * dump out stylesheet sections. */ static void stylesheets(Paragraph *p, Cstring *f) { Line* q; for ( ; p ; p = p->next ) { if ( p->typ == STYLE ) { for ( q = p->text; q ; q = q->next ) { Cswrite(f, T(q->text), S(q->text)); Csputc('\n', f); } } if ( p->down ) stylesheets(p->down, f); } } /* dump any embedded styles to a string */ int mkd_css(Document *d, char **res) { Cstring f; int size; if ( res && d && d->compiled ) { *res = 0; CREATE(f); RESERVE(f, 100); stylesheets(d->code, &f); if ( (size = S(f)) > 0 ) { EXPAND(f) = 0; /* HACK ALERT! HACK ALERT! HACK ALERT! */ *res = T(f);/* we know that a T(Cstring) is a character pointer */ /* so we can simply pick it up and carry it away, */ /* leaving the husk of the Ctring on the stack */ /* END HACK ALERT */ } else DELETE(f); return size; } return EOF; } /* dump any embedded styles to a file */ int mkd_generatecss(Document *d, FILE *f) { char *res; int written = EOF, size = mkd_css(d, &res); if ( size > 0 ) written = fwrite(res, 1, size, f); if ( res ) free(res); return (written == size) ? size : EOF; } discount-2.1.7/cstring.h000066400000000000000000000046351222516442300152040ustar00rootroot00000000000000/* two template types: STRING(t) which defines a pascal-style string * of element (t) [STRING(char) is the closest to the pascal string], * and ANCHOR(t) which defines a baseplate that a linked list can be * built up from. [The linked list /must/ contain a ->next pointer * for linking the list together with.] */ #ifndef _CSTRING_D #define _CSTRING_D #include #include #ifndef __WITHOUT_AMALLOC # include "amalloc.h" #endif /* expandable Pascal-style string. */ #define STRING(type) struct { type *text; int size, alloc; } #define CREATE(x) ( (T(x) = (void*)0), (S(x) = (x).alloc = 0) ) #define EXPAND(x) (S(x)++)[(S(x) < (x).alloc) \ ? (T(x)) \ : (T(x) = T(x) ? realloc(T(x), sizeof T(x)[0] * ((x).alloc += 100)) \ : malloc(sizeof T(x)[0] * ((x).alloc += 100)) )] #define DELETE(x) ALLOCATED(x) ? (free(T(x)), S(x) = (x).alloc = 0) \ : ( S(x) = 0 ) #define CLIP(t,i,sz) \ S(t) -= ( ((i) >= 0) && ((sz) > 0) && (((i)+(sz)) <= S(t)) ) ? \ (memmove(&T(t)[i], &T(t)[i+sz], (S(t)-(i+sz)+1)*sizeof(T(t)[0])), \ (sz)) : 0 #define RESERVE(x, sz) T(x) = ((x).alloc > S(x) + (sz) \ ? T(x) \ : T(x) \ ? realloc(T(x), sizeof T(x)[0] * ((x).alloc = 100+(sz)+S(x))) \ : malloc(sizeof T(x)[0] * ((x).alloc = 100+(sz)+S(x)))) #define SUFFIX(t,p,sz) \ memcpy(((S(t) += (sz)) - (sz)) + \ (T(t) = T(t) ? realloc(T(t), sizeof T(t)[0] * ((t).alloc += sz)) \ : malloc(sizeof T(t)[0] * ((t).alloc += sz))), \ (p), sizeof(T(t)[0])*(sz)) #define PREFIX(t,p,sz) \ RESERVE( (t), (sz) ); \ if ( S(t) ) { memmove(T(t)+(sz), T(t), S(t)); } \ memcpy( T(t), (p), (sz) ); \ S(t) += (sz) /* reference-style links (and images) are stored in an array */ #define T(x) (x).text #define S(x) (x).size #define ALLOCATED(x) (x).alloc /* abstract anchor type that defines a list base * with a function that attaches an element to * the end of the list. * * the list base field is named .text so that the T() * macro will work with it. */ #define ANCHOR(t) struct { t *text, *end; } #define E(t) ((t).end) #define ATTACH(t, p) ( T(t) ? ( (E(t)->next = (p)), (E(t) = (p)) ) \ : ( (T(t) = E(t) = (p)) ) ) typedef STRING(char) Cstring; extern void Csputc(int, Cstring *); extern int Csprintf(Cstring *, char *, ...); extern int Cswrite(Cstring *, char *, int); extern void Csreparse(Cstring *, char *, int, int); #endif/*_CSTRING_D*/ discount-2.1.7/docheader.c000066400000000000000000000014521222516442300154360ustar00rootroot00000000000000/* * docheader -- get values from the document header * * Copyright (C) 2007 David L Parsons. * The redistribution terms are provided in the COPYRIGHT file that must * be distributed with this source code. */ #include "config.h" #include #include #include #include "cstring.h" #include "markdown.h" #include "amalloc.h" static char * onlyifset(Line *l) { char *ret = T(l->text) + l->dle; return ret[0] ? ret : 0; } char * mkd_doc_title(Document *doc) { if ( doc && doc->title ) return onlyifset(doc->title); return 0; } char * mkd_doc_author(Document *doc) { if ( doc && doc->author ) return onlyifset(doc->author); return 0; } char * mkd_doc_date(Document *doc) { if ( doc && doc->date ) return onlyifset(doc->date); return 0; } discount-2.1.7/dumptree.c000066400000000000000000000055031222516442300153460ustar00rootroot00000000000000/* markdown: a C implementation of John Gruber's Markdown markup language. * * Copyright (C) 2007 David L Parsons. * The redistribution terms are provided in the COPYRIGHT file that must * be distributed with this source code. */ #include #include "markdown.h" #include "cstring.h" #include "amalloc.h" struct frame { int indent; char c; }; typedef STRING(struct frame) Stack; static char * Pptype(int typ) { switch (typ) { case WHITESPACE: return "whitespace"; case CODE : return "code"; case QUOTE : return "quote"; case MARKUP : return "markup"; case HTML : return "html"; case DL : return "dl"; case UL : return "ul"; case OL : return "ol"; case LISTITEM : return "item"; case HDR : return "header"; case HR : return "hr"; case TABLE : return "table"; case SOURCE : return "source"; case STYLE : return "style"; default : return "mystery node!"; } } static void pushpfx(int indent, char c, Stack *sp) { struct frame *q = &EXPAND(*sp); q->indent = indent; q->c = c; } static void poppfx(Stack *sp) { S(*sp)--; } static void changepfx(Stack *sp, char c) { char ch; if ( !S(*sp) ) return; ch = T(*sp)[S(*sp)-1].c; if ( ch == '+' || ch == '|' ) T(*sp)[S(*sp)-1].c = c; } static void printpfx(Stack *sp, FILE *f) { int i; char c; if ( !S(*sp) ) return; c = T(*sp)[S(*sp)-1].c; if ( c == '+' || c == '-' ) { fprintf(f, "--%c", c); T(*sp)[S(*sp)-1].c = (c == '-') ? ' ' : '|'; } else for ( i=0; i < S(*sp); i++ ) { if ( i ) fprintf(f, " "); fprintf(f, "%*s%c", T(*sp)[i].indent + 2, " ", T(*sp)[i].c); if ( T(*sp)[i].c == '`' ) T(*sp)[i].c = ' '; } fprintf(f, "--"); } static void dumptree(Paragraph *pp, Stack *sp, FILE *f) { int count; Line *p; int d; static char *Begin[] = { 0, "P", "center" }; while ( pp ) { if ( !pp->next ) changepfx(sp, '`'); printpfx(sp, f); d = fprintf(f, "[%s", Pptype(pp->typ)); if ( pp->ident ) d += fprintf(f, " %s", pp->ident); if ( pp->align > 1 ) d += fprintf(f, ", <%s>", Begin[pp->align]); for (count=0, p=pp->text; p; ++count, (p = p->next) ) ; if ( count ) d += fprintf(f, ", %d line%s", count, (count==1)?"":"s"); d += fprintf(f, "]"); if ( pp->down ) { pushpfx(d, pp->down->next ? '+' : '-', sp); dumptree(pp->down, sp, f); poppfx(sp); } else fputc('\n', f); pp = pp->next; } } int mkd_dump(Document *doc, FILE *out, int flags, char *title) { Stack stack; if (mkd_compile(doc, flags) ) { CREATE(stack); pushpfx(fprintf(out, "%s", title), doc->code->next ? '+' : '-', &stack); dumptree(doc->code, &stack, out); DELETE(stack); mkd_cleanup(doc); return 0; } return -1; } discount-2.1.7/emmatch.c000066400000000000000000000101201222516442300151260ustar00rootroot00000000000000/* markdown: a C implementation of John Gruber's Markdown markup language. * * Copyright (C) 2010 David 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 "config.h" #include "cstring.h" #include "markdown.h" #include "amalloc.h" /* emmatch: the emphasis mangler that's run after a block * of html has been generated. * * It should create MarkdownTest_1.0 (and _1.0.3) * compatable emphasis for non-pathological cases * and it should fail in a standards-compliant way * when someone attempts to feed it junk. * * Emmatching is done after the input has been * processed into a STRING (f->Q) of text and * emphasis blocks. After ___mkd_emblock() finishes, * it truncates f->Q and leaves the rendered paragraph * if f->out. */ /* empair() -- find the NEAREST matching emphasis token (or * subtoken of a 3+ long emphasis token. */ static int empair(MMIOT *f, int first, int last, int match) { int i; block *begin, *p; begin = &T(f->Q)[first]; for (i=first+1; i <= last; i++) { p = &T(f->Q)[i]; if ( (p->b_type != bTEXT) && (p->b_count <= 0) ) continue; /* break? */ if ( p->b_type == begin->b_type ) { if ( p->b_count == match ) /* exact match */ return i; if ( p->b_count > 2 ) /* fuzzy match */ return i; } } return 0; } /* empair */ /* emfill() -- if an emphasis token has leftover stars or underscores, * convert them back into character and append them to b_text. */ static void emfill(block *p) { int j; if ( p->b_type == bTEXT ) return; for (j=0; j < p->b_count; j++) EXPAND(p->b_text) = p->b_char; p->b_count = 0; } /* emfill */ static void emclose(MMIOT *f, int first, int last) { int j; for (j=first+1; jQ)[j]); } static struct emtags { char open[10]; char close[10]; int size; } emtags[] = { { "" , "", 5 }, { "", "", 9 } }; static void emblock(MMIOT*,int,int); /* emmatch() -- match emphasis for a single emphasis token. */ static void emmatch(MMIOT *f, int first, int last) { block *start = &T(f->Q)[first]; int e, e2, match; switch (start->b_count) { case 2: if ( e = empair(f,first,last,match=2) ) break; case 1: e = empair(f,first,last,match=1); break; case 0: return; default: e = empair(f,first,last,1); e2= empair(f,first,last,2); if ( e2 >= e ) { e = e2; match = 2; } else match = 1; break; } if ( e ) { /* if we found emphasis to match, match it, recursively call * emblock to match emphasis inside the new html block, add * the emphasis markers for the block, then (tail) recursively * call ourself to match any remaining emphasis on this token. */ block *end = &T(f->Q)[e]; end->b_count -= match; start->b_count -= match; emblock(f, first, e); PREFIX(start->b_text, emtags[match-1].open, emtags[match-1].size-1); SUFFIX(end->b_post, emtags[match-1].close, emtags[match-1].size); emmatch(f, first, last); } } /* emmatch */ /* emblock() -- walk a blocklist, attempting to match emphasis */ static void emblock(MMIOT *f, int first, int last) { int i; for ( i = first; i <= last; i++ ) if ( T(f->Q)[i].b_type != bTEXT ) emmatch(f, i, last); emclose(f, first, last); } /* emblock */ /* ___mkd_emblock() -- emblock a string of blocks, then concatenate the * resulting text onto f->out. */ void ___mkd_emblock(MMIOT *f) { int i; block *p; emblock(f, 0, S(f->Q)-1); for (i=0; i < S(f->Q); i++) { p = &T(f->Q)[i]; emfill(p); if ( S(p->b_post) ) { SUFFIX(f->out, T(p->b_post), S(p->b_post)); DELETE(p->b_post); } if ( S(p->b_text) ) { SUFFIX(f->out, T(p->b_text), S(p->b_text)); DELETE(p->b_text); } } S(f->Q) = 0; } /* ___mkd_emblock */ discount-2.1.7/flags.c000066400000000000000000000037121222516442300146150ustar00rootroot00000000000000#include #include "markdown.h" struct flagnames { DWORD flag; char *name; }; static struct flagnames flagnames[] = { { MKD_NOLINKS, "!LINKS" }, { MKD_NOIMAGE, "!IMAGE" }, { MKD_NOPANTS, "!PANTS" }, { MKD_NOHTML, "!HTML" }, { MKD_STRICT, "STRICT" }, { MKD_TAGTEXT, "TAGTEXT" }, { MKD_NO_EXT, "!EXT" }, { MKD_CDATA, "CDATA" }, { MKD_NOSUPERSCRIPT, "!SUPERSCRIPT" }, { MKD_NORELAXED, "!RELAXED" }, { MKD_NOTABLES, "!TABLES" }, { MKD_NOSTRIKETHROUGH,"!STRIKETHROUGH" }, { MKD_TOC, "TOC" }, { MKD_1_COMPAT, "MKD_1_COMPAT" }, { MKD_AUTOLINK, "AUTOLINK" }, { MKD_SAFELINK, "SAFELINK" }, { MKD_NOHEADER, "!HEADER" }, { MKD_TABSTOP, "TABSTOP" }, { MKD_NODIVQUOTE, "!DIVQUOTE" }, { MKD_NOALPHALIST, "!ALPHALIST" }, { MKD_NODLIST, "!DLIST" }, { MKD_EXTRA_FOOTNOTE, "FOOTNOTE" }, { MKD_NOSTYLE, "!STYLE" }, }; #define NR(x) (sizeof x/sizeof x[0]) void mkd_flags_are(FILE *f, DWORD flags, int htmlplease) { int i; int not, set, even=1; char *name; if ( htmlplease ) fprintf(f, "\n"); for (i=0; i < NR(flagnames); i++) { set = flags & flagnames[i].flag; name = flagnames[i].name; if ( not = (*name == '!') ) { ++name; set = !set; } if ( htmlplease ) { if ( even ) fprintf(f, " "); fprintf(f, ""); if ( !even ) fprintf(f, "\n"); } even = !even; } if ( htmlplease ) { if ( even ) fprintf(f, "\n"); fprintf(f, "
"); } else fputc(' ', f); if ( !set ) fprintf(f, htmlplease ? "" : "!"); fprintf(f, "%s", name); if ( htmlplease ) { if ( !set ) fprintf(f, ""); fprintf(f, "
\n"); } } void mkd_mmiot_flags(FILE *f, MMIOT *m, int htmlplease) { if ( m ) mkd_flags_are(f, m->flags, htmlplease); } discount-2.1.7/generate.c000066400000000000000000001105501222516442300153120ustar00rootroot00000000000000/* markdown: a C implementation of John Gruber's Markdown markup language. * * Copyright (C) 2007 David 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 "config.h" #include "cstring.h" #include "markdown.h" #include "amalloc.h" typedef int (*stfu)(const void*,const void*); typedef void (*spanhandler)(MMIOT*,int); /* forward declarations */ static void text(MMIOT *f); static Paragraph *display(Paragraph*, MMIOT*); /* externals from markdown.c */ int __mkd_footsort(Footnote *, Footnote *); /* * push text into the generator input buffer */ static void push(char *bfr, int size, MMIOT *f) { while ( size-- > 0 ) EXPAND(f->in) = *bfr++; } /* look characters ahead of the cursor. */ static inline int peek(MMIOT *f, int i) { i += (f->isp-1); return (i >= 0) && (i < S(f->in)) ? T(f->in)[i] : EOF; } /* pull a byte from the input buffer */ static inline int pull(MMIOT *f) { return ( f->isp < S(f->in) ) ? T(f->in)[f->isp++] : EOF; } /* return a pointer to the current position in the input buffer. */ static inline char* cursor(MMIOT *f) { return T(f->in) + f->isp; } static inline int isthisspace(MMIOT *f, int i) { int c = peek(f, i); if ( c == EOF ) return 1; if ( c & 0x80 ) return 0; return isspace(c) || (c < ' '); } static inline int isthisalnum(MMIOT *f, int i) { int c = peek(f, i); return (c != EOF) && isalnum(c); } static inline int isthisnonword(MMIOT *f, int i) { return isthisspace(f, i) || ispunct(peek(f,i)); } /* return/set the current cursor position */ #define mmiotseek(f,x) (f->isp = x) #define mmiottell(f) (f->isp) /* move n characters forward ( or -n characters backward) in the input buffer. */ static void shift(MMIOT *f, int i) { if (f->isp + i >= 0 ) f->isp += i; } /* Qchar() */ static void Qchar(int c, MMIOT *f) { block *cur; if ( S(f->Q) == 0 ) { cur = &EXPAND(f->Q); memset(cur, 0, sizeof *cur); cur->b_type = bTEXT; } else cur = &T(f->Q)[S(f->Q)-1]; EXPAND(cur->b_text) = c; } /* Qstring() */ static void Qstring(char *s, MMIOT *f) { while (*s) Qchar(*s++, f); } /* Qwrite() */ static void Qwrite(char *s, int size, MMIOT *f) { while (size-- > 0) Qchar(*s++, f); } /* Qprintf() */ static void Qprintf(MMIOT *f, char *fmt, ...) { char bfr[80]; va_list ptr; va_start(ptr,fmt); vsnprintf(bfr, sizeof bfr, fmt, ptr); va_end(ptr); Qstring(bfr, f); } /* Qem() */ static void Qem(MMIOT *f, char c, int count) { block *p = &EXPAND(f->Q); memset(p, 0, sizeof *p); p->b_type = (c == '*') ? bSTAR : bUNDER; p->b_char = c; p->b_count = count; memset(&EXPAND(f->Q), 0, sizeof(block)); } /* generate html from a markup fragment */ void ___mkd_reparse(char *bfr, int size, int flags, MMIOT *f, char *esc) { MMIOT sub; struct escaped e; ___mkd_initmmiot(&sub, f->footnotes); sub.flags = f->flags | flags; sub.cb = f->cb; sub.ref_prefix = f->ref_prefix; if ( esc ) { sub.esc = &e; e.up = f->esc; e.text = esc; } else sub.esc = f->esc; push(bfr, size, &sub); EXPAND(sub.in) = 0; S(sub.in)--; text(&sub); ___mkd_emblock(&sub); Qwrite(T(sub.out), S(sub.out), f); ___mkd_freemmiot(&sub, f->footnotes); } /* * check the escape list for special cases */ static int escaped(MMIOT *f, char c) { struct escaped *thing = f->esc; while ( thing ) { if ( strchr(thing->text, c) ) return 1; thing = thing->up; } return 0; } /* * write out a url, escaping problematic characters */ static void puturl(char *s, int size, MMIOT *f, int display) { unsigned char c; while ( size-- > 0 ) { c = *s++; if ( c == '\\' && size-- > 0 ) { c = *s++; if ( !( ispunct(c) || isspace(c) ) ) Qchar('\\', f); } if ( c == '&' ) Qstring("&", f); else if ( c == '<' ) Qstring("<", f); else if ( c == '"' ) Qstring("%22", f); else if ( isalnum(c) || ispunct(c) || (display && isspace(c)) ) Qchar(c, f); else if ( c == 003 ) /* untokenize ^C */ Qstring(" ", f); else Qprintf(f, "%%%02X", c); } } /* advance forward until the next character is not whitespace */ static int eatspace(MMIOT *f) { int c; for ( ; ((c=peek(f, 1)) != EOF) && isspace(c); pull(f) ) ; return c; } /* (match (a (nested (parenthetical (string.))))) */ static int parenthetical(int in, int out, MMIOT *f) { int size, indent, c; for ( indent=1,size=0; indent; size++ ) { if ( (c = pull(f)) == EOF ) return EOF; else if ( (c == '\\') && (peek(f,1) == out || peek(f,1) == in) ) { ++size; pull(f); } else if ( c == in ) ++indent; else if ( c == out ) --indent; } return size ? (size-1) : 0; } /* extract a []-delimited label from the input stream. */ static int linkylabel(MMIOT *f, Cstring *res) { char *ptr = cursor(f); int size; if ( (size = parenthetical('[',']',f)) != EOF ) { T(*res) = ptr; S(*res) = size; return 1; } return 0; } /* see if the quote-prefixed linky segment is actually a title. */ static int linkytitle(MMIOT *f, char quote, Footnote *ref) { int whence = mmiottell(f); char *title = cursor(f); char *e; register int c; while ( (c = pull(f)) != EOF ) { e = cursor(f); if ( c == quote ) { if ( (c = eatspace(f)) == ')' ) { T(ref->title) = 1+title; S(ref->title) = (e-title)-2; return 1; } } } mmiotseek(f, whence); return 0; } /* extract a =HHHxWWW size from the input stream */ static int linkysize(MMIOT *f, Footnote *ref) { int height=0, width=0; int whence = mmiottell(f); int c; if ( isspace(peek(f,0)) ) { pull(f); /* eat '=' */ for ( c = pull(f); isdigit(c); c = pull(f)) width = (width * 10) + (c - '0'); if ( c == 'x' ) { for ( c = pull(f); isdigit(c); c = pull(f)) height = (height*10) + (c - '0'); if ( isspace(c) ) c = eatspace(f); if ( (c == ')') || ((c == '\'' || c == '"') && linkytitle(f, c, ref)) ) { ref->height = height; ref->width = width; return 1; } } } mmiotseek(f, whence); return 0; } /* extract a <...>-encased url from the input stream. * (markdown 1.0.2b8 compatibility; older versions * of markdown treated the < and > as syntactic * sugar that didn't have to be there. 1.0.2b8 * requires a closing >, and then falls into the * title or closing ) */ static int linkybroket(MMIOT *f, int image, Footnote *p) { int c; int good = 0; T(p->link) = cursor(f); for ( S(p->link)=0; (c = pull(f)) != '>'; ++S(p->link) ) { /* pull in all input until a '>' is found, or die trying. */ if ( c == EOF ) return 0; else if ( (c == '\\') && ispunct(peek(f,2)) ) { ++S(p->link); pull(f); } } c = eatspace(f); /* next nonspace needs to be a title, a size, or ) */ if ( ( c == '\'' || c == '"' ) && linkytitle(f,c,p) ) good=1; else if ( image && (c == '=') && linkysize(f,p) ) good=1; else good=( c == ')' ); if ( good ) { if ( peek(f, 1) == ')' ) pull(f); ___mkd_tidy(&p->link); } return good; } /* linkybroket */ /* extract a (-prefixed url from the input stream. * the label is either of the format ``, where I * extract until I find a >, or it is of the format * `text`, where I extract until I reach a ')', a quote, * or (if image) a '=' */ static int linkyurl(MMIOT *f, int image, Footnote *p) { int c; int mayneedtotrim=0; if ( (c = eatspace(f)) == EOF ) return 0; if ( c == '<' ) { pull(f); if ( !(f->flags & MKD_1_COMPAT) ) return linkybroket(f,image,p); mayneedtotrim=1; } T(p->link) = cursor(f); for ( S(p->link)=0; (c = peek(f,1)) != ')'; ++S(p->link) ) { if ( c == EOF ) return 0; else if ( (c == '"' || c == '\'') && linkytitle(f, c, p) ) break; else if ( image && (c == '=') && linkysize(f, p) ) break; else if ( (c == '\\') && ispunct(peek(f,2)) ) { ++S(p->link); pull(f); } pull(f); } if ( peek(f, 1) == ')' ) pull(f); ___mkd_tidy(&p->link); if ( mayneedtotrim && (T(p->link)[S(p->link)-1] == '>') ) --S(p->link); return 1; } /* prefixes for */ static struct _protocol { char *name; int nlen; } protocol[] = { #define _aprotocol(x) { x, (sizeof x)-1 } _aprotocol( "https:" ), _aprotocol( "http:" ), _aprotocol( "news:" ), _aprotocol( "ftp:" ), #undef _aprotocol }; #define NRPROTOCOLS (sizeof protocol / sizeof protocol[0]) static int isautoprefix(char *text, int size) { int i; struct _protocol *p; for (i=0, p=protocol; i < NRPROTOCOLS; i++, p++) if ( (size >= p->nlen) && strncasecmp(text, p->name, p->nlen) == 0 ) return 1; return 0; } /* * all the tag types that linkylinky can produce are * defined by this structure. */ typedef struct linkytype { char *pat; int szpat; char *link_pfx; /* tag prefix and link pointer (eg: "" */ char *text_sfx; /* text suffix (eg: "" */ int flags; /* reparse flags */ int kind; /* tag is url or something else? */ #define IS_URL 0x01 } linkytype; static linkytype imaget = { 0, 0, "\"",", MKD_NOIMAGE|MKD_TAGTEXT, IS_URL }; static linkytype linkt = { 0, 0, "", "", MKD_NOLINKS, IS_URL }; /* * pseudo-protocols for [][]; * * id: generates tag * class: generates tag * raw: just dump the link without any processing */ static linkytype specials[] = { { "id:", 3, "", "", 0, 0 }, { "raw:", 4, 0, 0, 0, 0, 0, MKD_NOHTML, 0 }, { "lang:", 5, "", "", 0, 0 }, { "abbr:", 5, "", "", 0, 0 }, { "class:", 6, "", "", 0, 0 }, } ; #define NR(x) (sizeof x / sizeof x[0]) /* see if t contains one of our pseudo-protocols. */ static linkytype * pseudo(Cstring t) { int i; linkytype *r; for ( i=0, r=specials; i < NR(specials); i++,r++ ) { if ( (S(t) > r->szpat) && (strncasecmp(T(t), r->pat, r->szpat) == 0) ) return r; } return 0; } /* print out the start of an `img' or `a' tag, applying callbacks as needed. */ static void printlinkyref(MMIOT *f, linkytype *tag, char *link, int size) { char *edit; if ( f->flags & IS_LABEL ) return; Qstring(tag->link_pfx, f); if ( tag->kind & IS_URL ) { if ( f->cb && f->cb->e_url && (edit = (*f->cb->e_url)(link, size, f->cb->e_data)) ) { puturl(edit, strlen(edit), f, 0); if ( f->cb->e_free ) (*f->cb->e_free)(edit, f->cb->e_data); } else puturl(link + tag->szpat, size - tag->szpat, f, 0); } else ___mkd_reparse(link + tag->szpat, size - tag->szpat, MKD_TAGTEXT, f, 0); Qstring(tag->link_sfx, f); if ( f->cb && f->cb->e_flags && (edit = (*f->cb->e_flags)(link, size, f->cb->e_data)) ) { Qchar(' ', f); Qstring(edit, f); if ( f->cb->e_free ) (*f->cb->e_free)(edit, f->cb->e_data); } } /* printlinkyref */ /* helper function for php markdown extra footnotes; allow the user to * define a prefix tag instead of just `fn` */ static char * p_or_nothing(p) MMIOT *p; { return p->ref_prefix ? p->ref_prefix : "fn"; } /* php markdown extra/daring fireball style print footnotes */ static int extra_linky(MMIOT *f, Cstring text, Footnote *ref) { if ( ref->flags & REFERENCED ) return 0; if ( f->flags & IS_LABEL ) ___mkd_reparse(T(text), S(text), linkt.flags, f, 0); else { ref->flags |= REFERENCED; ref->refnumber = ++ f->reference; Qprintf(f, "%d", p_or_nothing(f), ref->refnumber, p_or_nothing(f), ref->refnumber, ref->refnumber); } return 1; } /* extra_linky */ /* print out a linky (or fail if it's Not Allowed) */ static int linkyformat(MMIOT *f, Cstring text, int image, Footnote *ref) { linkytype *tag; if ( image ) tag = &imaget; else if ( tag = pseudo(ref->link) ) { if ( f->flags & (MKD_NO_EXT|MKD_SAFELINK) ) return 0; } else if ( (f->flags & MKD_SAFELINK) && T(ref->link) && (T(ref->link)[0] != '/') && !isautoprefix(T(ref->link), S(ref->link)) ) /* if MKD_SAFELINK, only accept links that are local or * a well-known protocol */ return 0; else tag = &linkt; if ( f->flags & tag->flags ) return 0; if ( f->flags & IS_LABEL ) ___mkd_reparse(T(text), S(text), tag->flags, f, 0); else if ( tag->link_pfx ) { printlinkyref(f, tag, T(ref->link), S(ref->link)); if ( tag->WxH ) { if ( ref->height ) Qprintf(f," height=\"%d\"", ref->height); if ( ref->width ) Qprintf(f, " width=\"%d\"", ref->width); } if ( S(ref->title) ) { Qstring(" title=\"", f); ___mkd_reparse(T(ref->title), S(ref->title), MKD_TAGTEXT, f, 0); Qchar('"', f); } Qstring(tag->text_pfx, f); ___mkd_reparse(T(text), S(text), tag->flags, f, 0); Qstring(tag->text_sfx, f); } else Qwrite(T(ref->link) + tag->szpat, S(ref->link) - tag->szpat, f); return 1; } /* linkyformat */ /* * process embedded links and images */ static int linkylinky(int image, MMIOT *f) { int start = mmiottell(f); Cstring name; Footnote key, *ref; int status = 0; int extra_footnote = 0; CREATE(name); memset(&key, 0, sizeof key); if ( linkylabel(f, &name) ) { if ( peek(f,1) == '(' ) { pull(f); if ( linkyurl(f, image, &key) ) status = linkyformat(f, name, image, &key); } else { int goodlink, implicit_mark = mmiottell(f); if ( isspace(peek(f,1)) ) pull(f); if ( peek(f,1) == '[' ) { pull(f); /* consume leading '[' */ goodlink = linkylabel(f, &key.tag); } else { /* new markdown implicit name syntax doesn't * require a second [] */ mmiotseek(f, implicit_mark); goodlink = !(f->flags & MKD_1_COMPAT); if ( (f->flags & MKD_EXTRA_FOOTNOTE) && (!image) && S(name) && T(name)[0] == '^' ) extra_footnote = 1; } if ( goodlink ) { if ( !S(key.tag) ) { DELETE(key.tag); T(key.tag) = T(name); S(key.tag) = S(name); } if ( ref = bsearch(&key, T(*f->footnotes), S(*f->footnotes), sizeof key, (stfu)__mkd_footsort) ) { if ( extra_footnote ) status = extra_linky(f,name,ref); else status = linkyformat(f, name, image, ref); } } } } DELETE(name); ___mkd_freefootnote(&key); if ( status == 0 ) mmiotseek(f, start); return status; } /* write a character to output, doing text escapes ( & -> &, * > -> > < -> < ) */ static void cputc(int c, MMIOT *f) { switch (c) { case '&': Qstring("&", f); break; case '>': Qstring(">", f); break; case '<': Qstring("<", f); break; default : Qchar(c, f); break; } } /* * convert an email address to a string of nonsense */ static void mangle(char *s, int len, MMIOT *f) { while ( len-- > 0 ) { Qstring("&#", f); Qprintf(f, COINTOSS() ? "x%02x;" : "%02d;", *((unsigned char*)(s++)) ); } } /* nrticks() -- count up a row of tick marks */ static int nrticks(int offset, int tickchar, MMIOT *f) { int tick = 0; while ( peek(f, offset+tick) == tickchar ) tick++; return tick; } /* nrticks */ /* matchticks() -- match a certain # of ticks, and if that fails * match the largest subset of those ticks. * * if a subset was matched, return the # of ticks * that were matched. */ static int matchticks(MMIOT *f, int tickchar, int ticks, int *endticks) { int size, count, c; int subsize=0, subtick=0; *endticks = ticks; for (size = 0; (c=peek(f,size+ticks)) != EOF; size ++) { if ( (c == tickchar) && ( count = nrticks(size+ticks,tickchar,f)) ) { if ( count == ticks ) return size; else if ( count ) { if ( (count > subtick) && (count < ticks) ) { subsize = size; subtick = count; } size += count; } } } if ( subsize ) { *endticks = subtick; return subsize; } return 0; } /* matchticks */ /* code() -- write a string out as code. The only characters that have * special meaning in a code block are * `<' and `&' , which * are /always/ expanded to < and & */ static void code(MMIOT *f, char *s, int length) { int i,c; for ( i=0; i < length; i++ ) if ( (c = s[i]) == 003) /* ^C: expand back to 2 spaces */ Qstring(" ", f); else if ( c == '\\' && (i < length-1) && escaped(f, s[i+1]) ) cputc(s[++i], f); else cputc(c, f); } /* code */ /* delspan() -- write out a chunk of text, blocking with ... */ static void delspan(MMIOT *f, int size) { Qstring("", f); ___mkd_reparse(cursor(f)-1, size, 0, f, 0); Qstring("", f); } /* codespan() -- write out a chunk of text as code, trimming one * space off the front and/or back as appropriate. */ static void codespan(MMIOT *f, int size) { int i=0; if ( size > 1 && peek(f, size-1) == ' ' ) --size; if ( peek(f,i) == ' ' ) ++i, --size; Qstring("", f); code(f, cursor(f)+(i-1), size); Qstring("", f); } /* codespan */ /* before letting a tag through, validate against * MKD_NOLINKS and MKD_NOIMAGE */ static int forbidden_tag(MMIOT *f) { int c = toupper(peek(f, 1)); if ( f->flags & MKD_NOHTML ) return 1; if ( c == 'A' && (f->flags & MKD_NOLINKS) && !isthisalnum(f,2) ) return 1; if ( c == 'I' && (f->flags & MKD_NOIMAGE) && strncasecmp(cursor(f)+1, "MG", 2) == 0 && !isthisalnum(f,4) ) return 1; return 0; } /* Check a string to see if it looks like a mail address * "looks like a mail address" means alphanumeric + some * specials, then a `@`, then alphanumeric + some specials, * but with a `.` */ static int maybe_address(char *p, int size) { int ok = 0; for ( ;size && (isalnum(*p) || strchr("._-+*", *p)); ++p, --size) ; if ( ! (size && *p == '@') ) return 0; --size, ++p; if ( size && *p == '.' ) return 0; for ( ;size && (isalnum(*p) || strchr("._-+", *p)); ++p, --size ) if ( *p == '.' && size > 1 ) ok = 1; return size ? 0 : ok; } /* The size-length token at cursor(f) is either a mailto:, an * implicit mailto:, one of the approved url protocols, or just * plain old text. If it's a mailto: or an approved protocol, * linkify it, otherwise say "no" */ static int process_possible_link(MMIOT *f, int size) { int address= 0; int mailto = 0; char *text = cursor(f); if ( f->flags & MKD_NOLINKS ) return 0; if ( (size > 7) && strncasecmp(text, "mailto:", 7) == 0 ) { /* if it says it's a mailto, it's a mailto -- who am * I to second-guess the user? */ address = 1; mailto = 7; /* 7 is the length of "mailto:"; we need this */ } else address = maybe_address(text, size); if ( address ) { Qstring("", f); mangle(text+mailto, size-mailto, f); Qstring("", f); return 1; } else if ( isautoprefix(text, size) ) { printlinkyref(f, &linkt, text, size); Qchar('>', f); puturl(text,size,f, 1); Qstring("", f); return 1; } return 0; } /* process_possible_link */ /* a < may be just a regular character, the start of an embedded html * tag, or the start of an . If it's an automatic * link, we also need to know if it's an email address because if it * is we need to mangle it in our futile attempt to cut down on the * spaminess of the rendered page. */ static int maybe_tag_or_link(MMIOT *f) { int c, size; int maybetag = 1; if ( f->flags & MKD_TAGTEXT ) return 0; for ( size=0; (c = peek(f, size+1)) != '>'; size++) { if ( c == EOF ) return 0; else if ( c == '\\' ) { maybetag=0; if ( peek(f, size+2) != EOF ) size++; } else if ( isspace(c) ) break; #if WITH_GITHUB_TAGS else if ( ! (c == '/' || c == '-' || c == '_' || isalnum(c) ) ) #else else if ( ! (c == '/' || isalnum(c) ) ) #endif maybetag=0; } if ( size ) { if ( maybetag || (size >= 3 && strncmp(cursor(f), "!--", 3) == 0) ) { /* It is not a html tag unless we find the closing '>' in * the same block. */ while ( (c = peek(f, size+1)) != '>' ) if ( c == EOF ) return 0; else size++; if ( forbidden_tag(f) ) return 0; Qchar('<', f); while ( ((c = peek(f, 1)) != EOF) && (c != '>') ) Qchar(pull(f), f); return 1; } else if ( !isspace(c) && process_possible_link(f, size) ) { shift(f, size+1); return 1; } } return 0; } /* autolinking means that all inline html is . A * autolink url is alphanumerics, slashes, periods, underscores, * the at sign, colon, and the % character. */ static int maybe_autolink(MMIOT *f) { register int c; int size; /* greedily scan forward for the end of a legitimate link. */ for ( size=0; (c=peek(f, size+1)) != EOF; size++ ) if ( c == '\\' ) { if ( peek(f, size+2) != EOF ) ++size; } else if ( isspace(c) || strchr("'\"()[]{}<>`", c) ) break; if ( (size > 1) && process_possible_link(f, size) ) { shift(f, size); return 1; } return 0; } /* smartyquote code that's common for single and double quotes */ static int smartyquote(int *flags, char typeofquote, MMIOT *f) { int bit = (typeofquote == 's') ? 0x01 : 0x02; if ( bit & (*flags) ) { if ( isthisnonword(f,1) ) { Qprintf(f, "&r%cquo;", typeofquote); (*flags) &= ~bit; return 1; } } else if ( isthisnonword(f,-1) && peek(f,1) != EOF ) { Qprintf(f, "&l%cquo;", typeofquote); (*flags) |= bit; return 1; } return 0; } static int islike(MMIOT *f, char *s) { int len; int i; if ( s[0] == '|' ) { if ( !isthisnonword(f, -1) ) return 0; ++s; } if ( !(len = strlen(s)) ) return 0; if ( s[len-1] == '|' ) { if ( !isthisnonword(f,len-1) ) return 0; len--; } for (i=1; i < len; i++) if (tolower(peek(f,i)) != s[i]) return 0; return 1; } static struct smarties { char c0; char *pat; char *entity; int shift; } smarties[] = { { '\'', "'s|", "rsquo", 0 }, { '\'', "'t|", "rsquo", 0 }, { '\'', "'re|", "rsquo", 0 }, { '\'', "'ll|", "rsquo", 0 }, { '\'', "'ve|", "rsquo", 0 }, { '\'', "'m|", "rsquo", 0 }, { '\'', "'d|", "rsquo", 0 }, { '-', "---", "mdash", 2 }, { '-', "--", "ndash", 1 }, { '.', "...", "hellip", 2 }, { '.', ". . .", "hellip", 4 }, { '(', "(c)", "copy", 2 }, { '(', "(r)", "reg", 2 }, { '(', "(tm)", "trade", 3 }, { '3', "|3/4|", "frac34", 2 }, { '3', "|3/4ths|", "frac34", 2 }, { '1', "|1/2|", "frac12", 2 }, { '1', "|1/4|", "frac14", 2 }, { '1', "|1/4th|", "frac14", 2 }, { '&', "�", 0, 3 }, } ; #define NRSMART ( sizeof smarties / sizeof smarties[0] ) /* Smarty-pants-style chrome for quotes, -, ellipses, and (r)(c)(tm) */ static int smartypants(int c, int *flags, MMIOT *f) { int i; if ( f->flags & (MKD_NOPANTS|MKD_TAGTEXT|IS_LABEL) ) return 0; for ( i=0; i < NRSMART; i++) if ( (c == smarties[i].c0) && islike(f, smarties[i].pat) ) { if ( smarties[i].entity ) Qprintf(f, "&%s;", smarties[i].entity); shift(f, smarties[i].shift); return 1; } switch (c) { case '<' : return 0; case '\'': if ( smartyquote(flags, 's', f) ) return 1; break; case '"': if ( smartyquote(flags, 'd', f) ) return 1; break; case '`': if ( peek(f, 1) == '`' ) { int j = 2; while ( (c=peek(f,j)) != EOF ) { if ( c == '\\' ) j += 2; else if ( c == '`' ) break; else if ( c == '\'' && peek(f, j+1) == '\'' ) { Qstring("“", f); ___mkd_reparse(cursor(f)+1, j-2, 0, f, 0); Qstring("”", f); shift(f,j+1); return 1; } else ++j; } } break; } return 0; } /* smartypants */ /* process a body of text encased in some sort of tick marks. If it * works, generate the output and return 1, otherwise just return 0 and * let the caller figure it out. */ static int tickhandler(MMIOT *f, int tickchar, int minticks, int allow_space, spanhandler spanner) { int endticks, size; int tick = nrticks(0, tickchar, f); if ( !allow_space && isspace(peek(f,tick)) ) return 0; if ( (tick >= minticks) && (size = matchticks(f,tickchar,tick,&endticks)) ) { if ( endticks < tick ) { size += (tick - endticks); tick = endticks; } shift(f, tick); (*spanner)(f,size); shift(f, size+tick-1); return 1; } return 0; } #define tag_text(f) (f->flags & MKD_TAGTEXT) static void text(MMIOT *f) { int c, j; int rep; int smartyflags = 0; while (1) { if ( (f->flags & MKD_AUTOLINK) && isalpha(peek(f,1)) && !tag_text(f) ) maybe_autolink(f); c = pull(f); if (c == EOF) break; if ( smartypants(c, &smartyflags, f) ) continue; switch (c) { case 0: break; case 3: Qstring(tag_text(f) ? " " : "
", f); break; case '>': if ( tag_text(f) ) Qstring(">", f); else Qchar(c, f); break; case '"': if ( tag_text(f) ) Qstring(""", f); else Qchar(c, f); break; case '!': if ( peek(f,1) == '[' ) { pull(f); if ( tag_text(f) || !linkylinky(1, f) ) Qstring("![", f); } else Qchar(c, f); break; case '[': if ( tag_text(f) || !linkylinky(0, f) ) Qchar(c, f); break; /* A^B -> AB */ case '^': if ( (f->flags & (MKD_NOSUPERSCRIPT|MKD_STRICT|MKD_TAGTEXT)) || (isthisnonword(f,-1) && peek(f,-1) != ')') || isthisspace(f,1) ) Qchar(c,f); else { char *sup = cursor(f); int len = 0; if ( peek(f,1) == '(' ) { int here = mmiottell(f); pull(f); if ( (len = parenthetical('(',')',f)) <= 0 ) { mmiotseek(f,here); Qchar(c, f); break; } sup++; } else { while ( isthisalnum(f,1+len) ) ++len; if ( !len ) { Qchar(c,f); break; } shift(f,len); } Qstring("",f); ___mkd_reparse(sup, len, 0, f, "()"); Qstring("", f); } break; case '_': /* Underscores don't count if they're in the middle of a word */ if ( !(f->flags & (MKD_NORELAXED|MKD_STRICT)) && isthisalnum(f,-1) && isthisalnum(f,1) ) { Qchar(c, f); break; } case '*': /* Underscores & stars don't count if they're out in the middle * of whitespace */ if ( isthisspace(f,-1) && isthisspace(f,1) ) { Qchar(c, f); break; } /* else fall into the regular old emphasis case */ if ( tag_text(f) ) Qchar(c, f); else { for (rep = 1; peek(f,1) == c; pull(f) ) ++rep; Qem(f,c,rep); } break; case '~': if ( (f->flags & (MKD_NOSTRIKETHROUGH|MKD_TAGTEXT|MKD_STRICT)) || ! tickhandler(f,c,2,0, delspan) ) Qchar(c, f); break; case '`': if ( tag_text(f) || !tickhandler(f,c,1,1,codespan) ) Qchar(c, f); break; case '\\': switch ( c = pull(f) ) { case '&': Qstring("&", f); break; case '<': c = peek(f,1); if ( (c == EOF) || isspace(c) ) Qstring("<", f); else { /* Markdown.pl does not escape <[nonwhite] * sequences */ Qchar('\\', f); shift(f, -1); } break; case '^': if ( f->flags & (MKD_STRICT|MKD_NOSUPERSCRIPT) ) { Qchar('\\', f); shift(f,-1); break; } Qchar(c, f); break; case ':': case '|': if ( f->flags & MKD_NOTABLES ) { Qchar('\\', f); shift(f,-1); break; } Qchar(c, f); break; case EOF: Qchar('\\', f); break; default: if ( escaped(f,c) || strchr(">#.-+{}]![*_\\()`", c) ) Qchar(c, f); else { Qchar('\\', f); shift(f, -1); } break; } break; case '<': if ( !maybe_tag_or_link(f) ) Qstring("<", f); break; case '&': j = (peek(f,1) == '#' ) ? 2 : 1; while ( isthisalnum(f,j) ) ++j; if ( peek(f,j) != ';' ) Qstring("&", f); else Qchar(c, f); break; default: Qchar(c, f); break; } } /* truncate the input string after we've finished processing it */ S(f->in) = f->isp = 0; } /* text */ /* print a header block */ static void printheader(Paragraph *pp, MMIOT *f) { #if WITH_ID_ANCHOR Qprintf(f, "hnumber); if ( f->flags & MKD_TOC ) { Qstring(" id=\"", f); mkd_string_to_anchor(T(pp->text->text), S(pp->text->text), (mkd_sta_function_t)Qchar, f, 1); Qchar('"', f); } Qchar('>', f); #else if ( f->flags & MKD_TOC ) { Qstring("
text->text), S(pp->text->text), (mkd_sta_function_t)Qchar, f, 1); Qstring("\">\n", f); } Qprintf(f, "", pp->hnumber); #endif push(T(pp->text->text), S(pp->text->text), f); text(f); Qprintf(f, "", pp->hnumber); } enum e_alignments { a_NONE, a_CENTER, a_LEFT, a_RIGHT }; static char* alignments[] = { "", " style=\"text-align:center;\"", " style=\"text-align:left;\"", " style=\"text-align:right;\"" }; typedef STRING(int) Istring; static int splat(Line *p, char *block, Istring align, int force, MMIOT *f) { int first, idx = p->dle, colno = 0; ___mkd_tidy(&p->text); if ( T(p->text)[S(p->text)-1] == '|' ) --S(p->text); Qstring("\n", f); while ( idx < S(p->text) ) { first = idx; if ( force && (colno >= S(align)-1) ) idx = S(p->text); else while ( (idx < S(p->text)) && (T(p->text)[idx] != '|') ) { if ( T(p->text)[idx] == '\\' ) ++idx; ++idx; } Qprintf(f, "<%s%s>", block, alignments[ (colno < S(align)) ? T(align)[colno] : a_NONE ]); ___mkd_reparse(T(p->text)+first, idx-first, 0, f, "|"); Qprintf(f, "\n", block); idx++; colno++; } if ( force ) while (colno < S(align) ) { Qprintf(f, "<%s>\n", block, block); ++colno; } Qstring("\n", f); return colno; } static int printtable(Paragraph *pp, MMIOT *f) { /* header, dashes, then lines of content */ Line *hdr, *dash, *body; Istring align; int hcols,start; char *p; enum e_alignments it; hdr = pp->text; dash= hdr->next; body= dash->next; if ( T(hdr->text)[hdr->dle] == '|' ) { /* trim leading pipe off all lines */ Line *r; for ( r = pp->text; r; r = r->next ) r->dle ++; } /* figure out cell alignments */ CREATE(align); for (p=T(dash->text), start=dash->dle; start < S(dash->text); ) { char first, last; int end; last=first=0; for (end=start ; (end < S(dash->text)) && p[end] != '|'; ++ end ) { if ( p[end] == '\\' ) ++ end; else if ( !isspace(p[end]) ) { if ( !first) first = p[end]; last = p[end]; } } it = ( first == ':' ) ? (( last == ':') ? a_CENTER : a_LEFT) : (( last == ':') ? a_RIGHT : a_NONE ); EXPAND(align) = it; start = 1+end; } Qstring("\n", f); Qstring("\n", f); hcols = splat(hdr, "th", align, 0, f); Qstring("\n", f); if ( hcols < S(align) ) S(align) = hcols; else while ( hcols > S(align) ) EXPAND(align) = a_NONE; Qstring("\n", f); for ( ; body; body = body->next) splat(body, "td", align, 1, f); Qstring("\n", f); Qstring("
\n", f); DELETE(align); return 1; } static int printblock(Paragraph *pp, MMIOT *f) { Line *t = pp->text; static char *Begin[] = { "", "

", "

" }; static char *End[] = { "", "

","

" }; while (t) { if ( S(t->text) ) { if ( t->next && S(t->text) > 2 && T(t->text)[S(t->text)-2] == ' ' && T(t->text)[S(t->text)-1] == ' ' ) { push(T(t->text), S(t->text)-2, f); push("\003\n", 2, f); } else { ___mkd_tidy(&t->text); push(T(t->text), S(t->text), f); if ( t->next ) push("\n", 1, f); } } t = t->next; } Qstring(Begin[pp->align], f); text(f); Qstring(End[pp->align], f); return 1; } static void printcode(Line *t, char *lang, MMIOT *f) { int blanks; Qstring("
", f);
    for ( blanks = 0; t ; t = t->next ) {
	if ( S(t->text) > t->dle ) {
	    while ( blanks ) {
		Qchar('\n', f);
		--blanks;
	    }
	    code(f, T(t->text), S(t->text));
	    Qchar('\n', f);
	}
	else blanks++;
    }
    Qstring("
", f); } static void printhtml(Line *t, MMIOT *f) { int blanks; for ( blanks=0; t ; t = t->next ) if ( S(t->text) ) { for ( ; blanks; --blanks ) Qchar('\n', f); Qwrite(T(t->text), S(t->text), f); Qchar('\n', f); } else blanks++; } static void htmlify(Paragraph *p, char *block, char *arguments, MMIOT *f) { ___mkd_emblock(f); if ( block ) Qprintf(f, arguments ? "<%s %s>" : "<%s>", block, arguments); ___mkd_emblock(f); while (( p = display(p, f) )) { ___mkd_emblock(f); Qstring("\n\n", f); } if ( block ) Qprintf(f, "", block); ___mkd_emblock(f); } static void definitionlist(Paragraph *p, MMIOT *f) { Line *tag; if ( p ) { Qstring("
\n", f); for ( ; p ; p = p->next) { for ( tag = p->text; tag; tag = tag->next ) { Qstring("
", f); ___mkd_reparse(T(tag->text), S(tag->text), 0, f, 0); Qstring("
\n", f); } htmlify(p->down, "dd", p->ident, f); Qchar('\n', f); } Qstring("
", f); } } static void listdisplay(int typ, Paragraph *p, MMIOT* f) { if ( p ) { Qprintf(f, "<%cl", (typ==UL)?'u':'o'); if ( typ == AL ) Qprintf(f, " type=\"a\""); Qprintf(f, ">\n"); for ( ; p ; p = p->next ) { htmlify(p->down, "li", p->ident, f); Qchar('\n', f); } Qprintf(f, "\n", (typ==UL)?'u':'o'); } } /* dump out a Paragraph in the desired manner */ static Paragraph* display(Paragraph *p, MMIOT *f) { if ( !p ) return 0; switch ( p->typ ) { case STYLE: case WHITESPACE: break; case HTML: printhtml(p->text, f); break; case CODE: printcode(p->text, p->lang, f); break; case QUOTE: htmlify(p->down, p->ident ? "div" : "blockquote", p->ident, f); break; case UL: case OL: case AL: listdisplay(p->typ, p->down, f); break; case DL: definitionlist(p->down, f); break; case HR: Qstring("
", f); break; case HDR: printheader(p, f); break; case TABLE: printtable(p, f); break; case SOURCE: htmlify(p->down, 0, 0, f); break; default: printblock(p, f); break; } return p->next; } /* dump out a list of footnotes */ static void mkd_extra_footnotes(MMIOT *m) { int j, i; Footnote *t; if ( m->reference == 0 ) return; Csprintf(&m->out, "\n
\n
\n
    \n"); for ( i=1; i <= m->reference; i++ ) { for ( j=0; j < S(*m->footnotes); j++ ) { t = &T(*m->footnotes)[j]; if ( (t->refnumber == i) && (t->flags & REFERENCED) ) { Csprintf(&m->out, "
  1. \n

    ", p_or_nothing(m), t->refnumber); Csreparse(&m->out, T(t->title), S(t->title), 0); Csprintf(&m->out, "", p_or_nothing(m), t->refnumber); Csprintf(&m->out, "

  2. \n"); } } } Csprintf(&m->out, "
\n
\n"); } /* return a pointer to the compiled markdown * document. */ int mkd_document(Document *p, char **res) { int size; if ( p && p->compiled ) { if ( ! p->html ) { htmlify(p->code, 0, 0, p->ctx); if ( p->ctx->flags & MKD_EXTRA_FOOTNOTE ) mkd_extra_footnotes(p->ctx); p->html = 1; } size = S(p->ctx->out); if ( (size == 0) || T(p->ctx->out)[size-1] ) EXPAND(p->ctx->out) = 0; *res = T(p->ctx->out); return size; } return EOF; } discount-2.1.7/github_flavoured.c000066400000000000000000000042141222516442300170500ustar00rootroot00000000000000 /* * github_flavoured -- implement the obnoxious "returns are hard newlines" * feature in github flavoured markdown. * * Copyright (C) 2012 David L Parsons. * The redistribution terms are provided in the COPYRIGHT file that must * be distributed with this source code. */ #include "config.h" #include #include #include #include "cstring.h" #include "markdown.h" #include "amalloc.h" /* build a Document from any old input. */ typedef int (*getc_func)(void*); Document * gfm_populate(getc_func getc, void* ctx, int flags) { Cstring line; Document *a = __mkd_new_Document(); int c; int pandoc = 0; if ( !a ) return 0; a->tabstop = (flags & MKD_TABSTOP) ? 4 : TABSTOP; CREATE(line); while ( (c = (*getc)(ctx)) != EOF ) { if ( c == '\n' ) { if ( pandoc != EOF && pandoc < 3 ) { if ( S(line) && (T(line)[0] == '%') ) pandoc++; else pandoc = EOF; } if (pandoc == EOF) { EXPAND(line) = ' '; EXPAND(line) = ' '; } __mkd_enqueue(a, &line); S(line) = 0; } else if ( isprint(c) || isspace(c) || (c & 0x80) ) EXPAND(line) = c; } if ( S(line) ) __mkd_enqueue(a, &line); DELETE(line); if ( (pandoc == 3) && !(flags & (MKD_NOHEADER|MKD_STRICT)) ) { /* the first three lines started with %, so we have a header. * clip the first three lines out of content and hang them * off header. */ Line *headers = T(a->content); a->title = headers; __mkd_header_dle(a->title); a->author= headers->next; __mkd_header_dle(a->author); a->date = headers->next->next; __mkd_header_dle(a->date); T(a->content) = headers->next->next->next; } return a; } /* convert a block of text into a linked list */ Document * gfm_string(const char *buf, int len, DWORD flags) { struct string_stream about; about.data = buf; about.size = len; return gfm_populate((getc_func)__mkd_io_strget, &about, flags & INPUT_MASK); } /* convert a file into a linked list */ Document * gfm_in(FILE *f, DWORD flags) { return gfm_populate((getc_func)fgetc, f, flags & INPUT_MASK); } discount-2.1.7/html5.c000066400000000000000000000007021222516442300145460ustar00rootroot00000000000000/* block-level tags for passing html5 blocks through the blender */ #include "tags.h" void mkd_with_html5_tags() { static int populated = 0; if ( populated ) return; populated = 1; mkd_define_tag("ASIDE", 0); mkd_define_tag("FOOTER", 0); mkd_define_tag("HEADER", 0); mkd_define_tag("HGROUP", 0); mkd_define_tag("NAV", 0); mkd_define_tag("SECTION", 0); mkd_define_tag("ARTICLE", 0); mkd_sort_tags(); } discount-2.1.7/main.c000066400000000000000000000103121222516442300144370ustar00rootroot00000000000000/* * markdown: convert a single markdown document into html */ /* * Copyright (C) 2007 David 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 "config.h" #include "amalloc.h" #include "pgm_options.h" #include "tags.h" #if HAVE_LIBGEN_H #include #endif #ifndef HAVE_BASENAME #include 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); } main(int argc, char **argv) { int opt; int rc; mkd_flag_t flags = 0; int debug = 0; int toc = 0; int content = 1; int version = 0; int with_html5 = 0; int styles = 0; int use_mkd_line = 0; int github_flavoured = 0; char *extra_footnote_prefix = 0; char *urlflags = 0; char *text = 0; char *ofile = 0; char *urlbase = 0; char *q; MMIOT *doc; if ( q = getenv("MARKDOWN_FLAGS") ) flags = strtol(q, 0, 0); pgm = basename(argv[0]); opterr = 1; while ( (opt=getopt(argc, argv, "5b:C:df:E:F:Gno:s:St:TV")) != EOF ) { switch (opt) { case '5': with_html5 = 1; break; case 'b': urlbase = optarg; break; case 'd': debug = 1; break; case 'V': version++; break; case 'E': urlflags = optarg; break; case 'F': if ( strcmp(optarg, "?") == 0 ) { show_flags(0); exit(0); } else flags = strtol(optarg, 0, 0); break; case 'f': if ( strcmp(optarg, "?") == 0 ) { show_flags(1); exit(0); } else if ( !set_flag(&flags, optarg) ) complain("unknown option <%s>", optarg); break; case 'G': github_flavoured = 1; break; case 'n': content = 0; break; case 's': text = optarg; break; case 'S': styles = 1; break; case 't': text = optarg; use_mkd_line = 1; break; case 'T': toc = 1; break; case 'C': extra_footnote_prefix = optarg; break; case 'o': if ( ofile ) { complain("Too many -o options"); exit(1); } if ( !freopen(ofile = optarg, "w", stdout) ) { perror(ofile); exit(1); } break; default: fprintf(stderr, "usage: %s [-dTV] [-b url-base]" " [-F bitmap] [-f {+-}flags]" " [-o ofile] [-s text]" " [-t text] [file]\n", pgm); exit(1); } } if ( version ) { printf("%s: discount %s%s", pgm, markdown_version, with_html5 ? " +html5":""); if ( version > 1 ) mkd_flags_are(stdout, flags, 0); putchar('\n'); exit(0); } argc -= optind; argv += optind; if ( with_html5 ) mkd_with_html5_tags(); if ( use_mkd_line ) rc = mkd_generateline( text, strlen(text), stdout, flags); else { if ( text ) { doc = github_flavoured ? gfm_string(text, strlen(text), flags) : mkd_string(text, strlen(text), flags) ; if ( !doc ) { perror(text); exit(1); } } else { if ( argc && !freopen(argv[0], "r", stdin) ) { perror(argv[0]); exit(1); } doc = github_flavoured ? gfm_in(stdin,flags) : mkd_in(stdin,flags); if ( !doc ) { perror(argc ? argv[0] : "stdin"); exit(1); } } if ( urlbase ) mkd_basename(doc, urlbase); if ( urlflags ) { mkd_e_data(doc, urlflags); mkd_e_flags(doc, e_flags); } if ( extra_footnote_prefix ) mkd_ref_prefix(doc, extra_footnote_prefix); if ( debug ) rc = mkd_dump(doc, stdout, 0, argc ? basename(argv[0]) : "stdin"); else { rc = 1; if ( mkd_compile(doc, flags) ) { rc = 0; if ( styles ) mkd_generatecss(doc, stdout); if ( toc ) mkd_generatetoc(doc, stdout); if ( content ) mkd_generatehtml(doc, stdout); mkd_cleanup(doc); } } } mkd_deallocate_tags(); adump(); exit( (rc == 0) ? 0 : errno ); } discount-2.1.7/makepage.1000066400000000000000000000013471222516442300152130ustar00rootroot00000000000000.\" %A% .\" .Dd January 10, 2010 .Dt MAKEPAGE 1 .Os MASTODON .Sh NAME .Nm makepage .Nd convert markdown input to a fully-formed xhtml page .Sh SYNOPSIS .Nm .Op Fl V .Op Fl F Pa bitmap .Op Fl f Ar flags .Op Pa file .Sh DESCRIPTION The .Nm utility parses a .Xr markdown 7 Ns -formatted .Pa textfile .Pq or stdin if not specified, compiles it, then prints a fully-formed xhtml page to stdout. .Pp The .Fl F , .Fl f , and .Fl V flags are identical to the same options in .Xr markdown 1 . .Pp .Nm is part of discount. .Sh RETURN VALUES The .Nm utility exits 0 on success, and >0 if an error occurs. .Sh SEE ALSO .Xr markdown 1 , .Xr markdown 3 , .Xr markdown 7 , .Xr mkd-extensions 7 . .Sh AUTHOR .An David Parsons .Pq Li orc@pell.chi.il.us discount-2.1.7/makepage.c000066400000000000000000000031701222516442300152710ustar00rootroot00000000000000/* * makepage: Use mkd_xhtmlpage() to convert markdown input to a * fully-formed xhtml page. */ #include #include #include #include #include #include "config.h" #include "pgm_options.h" #ifndef HAVE_BASENAME char* basename(char *p) { char *ret = strrchr(p, '/'); return ret ? (1+ret) : p; } #endif char *pgm = "makepage"; main(argc, argv) int argc; char **argv; { MMIOT *doc; char *q; int version = 0; int opt; mkd_flag_t flags = 0; if ( (q = getenv("MARKDOWN_FLAGS")) ) flags = strtol(q, 0, 0); opterr = 1; while ( (opt=getopt(argc, argv, "F:f:V")) != EOF ) { switch (opt) { case 'V': version++; break; case 'F': if ( strcmp(optarg, "?") == 0 ) { show_flags(0); exit(0); } else flags = strtol(optarg, 0, 0); break; case 'f': if ( strcmp(optarg, "?") == 0 ) { show_flags(1); exit(0); } else if ( !set_flag(&flags, optarg) ) fprintf(stderr, "unknown option <%s>\n", optarg); break; default: fprintf(stderr, "usage: %s [-V] [-F bitmap] [-f {+-}flags]" " [file]\n", pgm); exit(1); } } argc -= optind; argv += optind; if ( version ) { printf("%s: discount %s", pgm, markdown_version); if ( version > 1 ) mkd_flags_are(stdout, flags, 0); putchar('\n'); exit(0); } if ( (argc > 1) && !freopen(argv[1], "r", stdin) ) { perror(argv[1]); exit(1); } if ( (doc = mkd_in(stdin, flags)) == 0 ) { perror( (argc > 1) ? argv[1] : "stdin" ); exit(1); } exit(mkd_xhtmlpage(doc, flags, stdout)); } discount-2.1.7/markdown.1000066400000000000000000000066021222516442300152620ustar00rootroot00000000000000.\" %A% .\" .Dd January 7, 2008 .Dt MARKDOWN 1 .Os MASTODON .Sh NAME .Nm markdown .Nd text to html conversion tool .Sh SYNOPSIS .Nm .Op Fl d .Op Fl T .Op Fl V .Op Fl b Ar url-base .Op Fl C Ar prefix .Op Fl F Pa bitmap .Op Fl f Ar flags .Op Fl n .Op Fl o Pa file .Op Fl S .Op Fl s Pa text .Op Fl t Pa text .Op Pa textfile .Sh DESCRIPTION The .Nm utility reads the .Xr markdown 7 Ns -formatted .Pa textfile .Pq or stdin if not specified, compiles it, and writes the html output to stdout. .Pp The options are as follows: .Bl -tag -width "-o file" .It Fl b Ar url-base Links in source beginning with / will be prefixed with .Ar url-base in the output. .It Fl C When processing markdown extra-style footnotes, use the given prefix instead of the default of .Ar fn . .It Fl d Instead of writing the html file, dump a parse tree to stdout. .It Fl f Ar flags Set or clear various translation flags. The flags are in a comma-delimited list, with an optional .Ar + (enable), .Ar - (disable), or .Ar no (disable) lprefix on each flag. .Bl -tag -width "definitionlist" .It Ar links Allow links. .It Ar image Allow images. .It Ar smarty Enable smartypants. .It Ar pants Enable smartypants. .It Ar html Allow raw html. .It Ar strict Disable superscript, strikethrough & relaxed emphasis. .It Ar ext Enable pseudo-protocols. .It Ar cdata Generate code for xml .Em ![CDATA[...]] . .It Ar superscript Enable superscript processing. .It Ar emphasis Emphasis happens .Em everywhere . .It Ar tables Don't process PHP Markdown Extra tables. .It Ar del Enable .Em ~~strikethrough~~ . .It Ar strikethrough Enable .Em ~~strikethrough~~ . .It Ar toc Enable table-of-contents processing. .It Ar 1.0 Compatibility with MarkdownTest_1.0 .It Ar autolink Make .Pa http://foo.com a link even without .Em <> . .It Ar safelink Paranoid check for link protocol. .It Ar header Process pandoc-style header blocks. .It Ar tabstop Expand tabs to 4 spaces. .It Ar divquote Allow .Pa >%class% blocks. .It Ar alphalist Allow alphabetic lists. .It Ar definitionlist Allow definition lists. .It Ar footnote Allow markdown extra-style footnotes. .It Ar styles Extract at the end of the line or a .Em at the beginning of a subsequent line. .Pp Be warned that style blocks work like footnote links -- no matter where you define them they are valid for the entire document. .Ss relaxed emphasis The rules for emphasis are changed so that a single .Ar _ will .Em not count as a emphasis character if it's in the middle of a word. This is primarily for documenting code, if you don't wish to have to backquote all code references. .Ss alpha lists Alphabetic lists (like regular numeric lists, but with alphabetic items) are supported. So: .nf a. this b. is c. an alphabetic d. list .fi will produce: .nf
  1. this
  2. is
  3. an alphabetic
  4. list
.fi .Ss tables .Ar "PHP Markdown Extra" tables are supported; input of the form .nf header|header ------|------ text | text .fi will produce: .nf
header header
text text
.fi The dashed line can also contain .Em : characters for formatting; if a .Em : is at the start of a column, it tells .Nm discount to align the cell contents to the left; if it's at the end, it aligns right, and if there's one at the start and at the end, it centers. .Ss strikethrough A strikethrough syntax is supported in much the same way that .Ar ` is used to define a section of code. If you enclose text with two or more tildes, such as .Em ~~erased text~~ it will be written as .Em "erased text" . Like code sections, you may use as many .Ar ~ as you want, but there must be as many starting tildes as closing tildes. .Ss markdown extra-style footnotes .Ar "PHP Markdown Extra" footnotes are supported. If a footnote link begins with a .Ar ^ , the first use of that footnote will generate a link down to the bottom of the rendered document, which will contain a numbered footnote with a link back to where the footnote was called. .Sh AUTHOR David Parsons .%T http://www.pell.portland.or.us/~orc/ .Sh SEE ALSO .Xr markdown 1 , .Xr markdown 3 , .Xr mkd-callbacks 3 , .Xr mkd-functions 3 , .Xr mkd-line 3 . .Pp .%T http://daringfireball.net/projects/markdown .Pp .%T http://michelf.com/projects/php-markdown discount-2.1.7/mkd-functions.3000066400000000000000000000101461222516442300162210ustar00rootroot00000000000000.\" .Dd January 18, 2008 .Dt MKD_FUNCTIONS 3 .Os Mastodon .Sh NAME .Nm mkd_functions .Nd access and process Markdown documents. .Sh LIBRARY Markdown .Pq libmarkdown , -lmarkdown .Sh SYNOPSIS .Fd #include .Ft int .Fn mkd_compile "MMIOT *document" "int flags" .Ft int .Fn mkd_css "MMIOT *document" "char **doc" .Ft int .Fn mkd_generatecss "MMIOT *document" "FILE *output" .Ft int .Fn mkd_document "MMIOT *document" "char **doc" .Ft int .Fn mkd_generatehtml "MMIOT *document" "FILE *output" .Ft int .Fn mkd_xhtmlpage "MMIOT *document" "int flags" "FILE *output" .Ft int .Fn mkd_toc "MMIOT *document" "char **doc" .Ft void .Fn mkd_generatetoc "MMIOT *document" "FILE *output" .Ft void .Fn mkd_cleanup "MMIOT*" .Ft char* .Fn mkd_doc_title "MMIOT*" .Ft char* .Fn mkd_doc_author "MMIOT*" .Ft char* .Fn mkd_doc_date "MMIOT*" .Sh DESCRIPTION .Pp The .Nm markdown format supported in this implementation includes Pandoc-style header and inline .Ar \ blocks, and the standard .Xr markdown 3 functions do not provide access to the data provided by either of those extensions. These functions give you access to that data, plus they provide a finer-grained way of converting .Em Markdown documents into HTML. .Pp Given a .Ar MMIOT* generated by .Fn mkd_in or .Fn mkd_string , .Fn mkd_compile compiles the document into .Em \ , .Em Pandoc , and .Em html sections. .Pp Once compiled, the document can be examined and written by the .Fn mkd_css , .Fn mkd_document , .Fn mkd_generatecss , .Fn mkd_generatehtml , .Fn mkd_generatetoc , .Fn mkd_toc , .Fn mkd_xhtmlpage , .Fn mkd_doc_title , .Fn mkd_doc_author , and .Fn mkd_doc_date functions. .Pp .Fn mkd_css allocates a string and populates it with any \ sections provided in the document, .Fn mkd_generatecss writes any \ sections to the output, .Fn mkd_document points .Ar text to the text of the document and returns the size of the document, .Fn mkd_generatehtml writes the rest of the document to the output, and .Fn mkd_doc_title , .Fn mkd_doc_author , .Fn mkd_doc_date are used to read the contents of a Pandoc header, if any. .Pp .Fn mkd_xhtmlpage writes a xhtml page containing the document. The regular set of flags can be passed. .Pp .Fn mkd_toc writes a document outline, in the form of a collection of nested lists with links to each header in the document, into a string allocated with .Fn malloc , and returns the size. .Pp .Fn mkd_generatetoc is like .Fn mkd_toc , except that it writes the document outline to the given .Pa FILE* argument. .Pp .Fn mkd_cleanup deletes a .Ar MMIOT* after processing is done. .Pp .Fn mkd_compile accepts the same flags that .Fn markdown and .Fn mkd_string do; .Bl -tag -width MKD_NOSTRIKETHROUGH -compact .It Ar MKD_NOIMAGE Do not process `![]' and remove .Em \ tags from the output. .It Ar MKD_NOLINKS Do not process `[]' and remove .Em \ tags from the output. .It Ar MKD_NOPANTS Do not do Smartypants-style mangling of quotes, dashes, or ellipses. .It Ar MKD_TAGTEXT Process the input as if you were inside a html tag. This means that no html tags will be generated, and .Fn mkd_compile will attempt to escape anything that might terribly confuse a web browser. .It Ar MKD_NO_EXT Do not process any markdown pseudo-protocols when handing .Ar [][] links. .It Ar MKD_NOHEADER Do not attempt to parse any Pandoc-style headers. .It Ar MKD_TOC Label all headers for use with the .Fn mkd_generatetoc function. .It Ar MKD_1_COMPAT MarkdownTest_1.0 compatibility flag; trim trailing spaces from the first line of code blocks and disable implicit reference links. .It Ar MKD_NOSTRIKETHROUGH Disable strikethrough support. .El .Sh RETURN VALUES The function .Fn mkd_compile returns 1 in the case of success, or 0 if the document is already compiled. The function .Fn mkd_generatecss returns the number of bytes written in the case of success, or EOF if an error occurred. The function .Fn mkd_generatehtml returns 0 on success, \-1 on failure. .Sh SEE ALSO .Xr markdown 1 , .Xr markdown 3 , .Xr mkd-line 3 , .Xr markdown 7 , .Xr mkd-extensions 7 , .Xr mmap 2 . .Pp http://daringfireball.net/projects/markdown/syntax .Sh BUGS Error handling is minimal at best. discount-2.1.7/mkd-line.3000066400000000000000000000017321222516442300151410ustar00rootroot00000000000000.\" .Dd January 18, 2008 .Dt MKD_LINE 3 .Os Mastodon .Sh NAME .Nm mkd_line .Nd do Markdown translation of small items .Sh LIBRARY Markdown .Pq libmarkdown , -lmarkdown .Sh SYNOPSIS .Fd #include .Ft int .Fn mkd_line "char *string" "int size" "char **doc" "int flags" .Ft int .Fn mkd_generateline "char *string" "int size" "FILE *output" "int flags" .Sh DESCRIPTION .Pp Occasionally one might want to do markdown translations on fragments of data, like the title of an weblog article, a date, or a simple signature line. .Nm mkd_line and .Nm mkd_generateline allow you to do markdown translations on small blocks of text. .Nm mkd_line allocates a buffer, then writes the translated text into that buffer, and .Nm mkd_generateline writes the output to the specified .Ar FILE* . .Sh SEE ALSO .Xr markdown 1 , .Xr markdown 3 , .Xr markdown 7 , .Xr mkd-extensions 7 , .Xr mmap 2 . .Pp http://daringfireball.net/projects/markdown/syntax .Sh BUGS Error handling is minimal at best. discount-2.1.7/mkd2html.1000066400000000000000000000016641222516442300151650ustar00rootroot00000000000000.\" %A% .\" .Dd January 10, 2010 .Dt MKD2HTML 1 .Os MASTODON .Sh NAME .Nm mkd2html .Nd markdown to html converter .Sh SYNOPSIS .Nm .Op Fl css Pa file .Op Fl header Pa string .Op Fl footer Pa string .Op Pa file .Sh DESCRIPTION .Nm utility parses a .Xr markdown 7 Ns -formatted .Pa textfile .Pq or stdin if not specified, and generates a web page. It reads .Ar file or .Ar file.text and writes the result in .Ar file.html .Pq where file is the passed argument. .Pp .Nm is part of discount. .Sh OPTIONS .Bl -tag -width "-header string" .It Fl css Ar file Specifies a CSS file. .It Fl header Ar string Specifies a line to add to the
tag. .It Fl footer Ar string Specifies a line to add before the <\/body> tag. .El .Sh RETURN VALUES The .Nm utility exits 0 on success, and >0 if an error occurs. .Sh SEE ALSO .Xr markdown 1 , .Xr markdown 3 , .Xr markdown 7 , .Xr mkd-extensions 7 . .Sh AUTHOR .An David Parsons .Pq Li orc@pell.chi.il.us discount-2.1.7/mkd2html.c000066400000000000000000000074431222516442300152500ustar00rootroot00000000000000/* * mkd2html: parse a markdown input file and generate a web page. * * usage: mkd2html [options] filename * or mkd2html [options] < markdown > html * * options * -css css-file * -header line-to-add-to-
* -footer line-to-add-before- * * example: * * mkd2html -cs /~orc/pages.css syntax * ( read syntax OR syntax.text, write syntax.html ) */ /* * Copyright (C) 2007 David L Parsons. * The redistribution terms are provided in the COPYRIGHT file that must * be distributed with this source code. */ #include "config.h" #include #include #include #ifdef HAVE_BASENAME # ifdef HAVE_LIBGEN_H # include # else # include # endif #endif #include #include "mkdio.h" #include "cstring.h" #include "amalloc.h" char *pgm = "mkd2html"; #ifndef HAVE_BASENAME char * basename(char *path) { char *p; if ( p = strrchr(path, '/') ) return 1+p; return path; } #endif void fail(char *why, ...) { va_list ptr; va_start(ptr,why); fprintf(stderr, "%s: ", pgm); vfprintf(stderr, why, ptr); fputc('\n', stderr); va_end(ptr); exit(1); } main(argc, argv) char **argv; { char *h; char *source = 0, *dest = 0; MMIOT *mmiot; int i; FILE *input, *output; STRING(char*) css, headers, footers; CREATE(css); CREATE(headers); CREATE(footers); pgm = basename(argv[0]); while ( argc > 1 ) { if ( strcmp(argv[1], "-css") == 0 ) { EXPAND(css) = argv[2]; argc -= 2; argv += 2; } else if ( strcmp(argv[1], "-header") == 0 ) { EXPAND(headers) = argv[2]; argc -= 2; argv += 2; } else if ( strcmp(argv[1], "-footer") == 0 ) { EXPAND(footers) = argv[2]; argc -= 2; argv += 2; } else break; } switch ( argc ) { char *p, *dot; case 1: input = stdin; output = stdout; break; case 2: case 3: dest = malloc(strlen(argv[argc-1]) + 6); source = malloc(strlen(argv[1]) + 6); if ( !(source && dest) ) fail("out of memory allocating name buffers"); strcpy(source, argv[1]); if (( p = strrchr(source, '/') )) p = source; else ++p; if ( (input = fopen(source, "r")) == 0 ) { strcat(source, ".text"); if ( (input = fopen(source, "r")) == 0 ) fail("can't open either %s or %s", argv[1], source); } strcpy(dest, source); if (( dot = strrchr(dest, '.') )) *dot = 0; strcat(dest, ".html"); if ( (output = fopen(dest, "w")) == 0 ) fail("can't write to %s", dest); break; default: fprintf(stderr, "usage: %s [opts] source [dest]\n", pgm); exit(1); } if ( (mmiot = mkd_in(input, 0)) == 0 ) fail("can't read %s", source ? source : "stdin"); if ( !mkd_compile(mmiot, 0) ) fail("couldn't compile input"); h = mkd_doc_title(mmiot); /* print a header */ fprintf(output, "\n" "\n" "\n" " \n", markdown_version); fprintf(output," "); for ( i=0; i < S(css); i++ ) fprintf(output, " \n", T(css)[i]); if ( h ) { fprintf(output," "); mkd_generateline(h, strlen(h), output, 0); fprintf(output, "\n"); } for ( i=0; i < S(headers); i++ ) fprintf(output, " %s\n", T(headers)[i]); fprintf(output, "\n" "\n"); /* print the compiled body */ mkd_generatehtml(mmiot, output); for ( i=0; i < S(footers); i++ ) fprintf(output, "%s\n", T(footers)[i]); fprintf(output, "\n" "\n"); mkd_cleanup(mmiot); exit(0); } discount-2.1.7/mkdio.c000066400000000000000000000151271222516442300146270ustar00rootroot00000000000000/* * mkdio -- markdown front end input functions * * Copyright (C) 2007 David L Parsons. * The redistribution terms are provided in the COPYRIGHT file that must * be distributed with this source code. */ #include "config.h" #include #include #include #include "cstring.h" #include "markdown.h" #include "amalloc.h" typedef ANCHOR(Line) LineAnchor; /* create a new blank Document */ Document* __mkd_new_Document() { Document *ret = calloc(sizeof(Document), 1); if ( ret ) { if ( ret->ctx = calloc(sizeof(MMIOT), 1) ) { ret->magic = VALID_DOCUMENT; return ret; } free(ret); } return 0; } /* add a line to the markdown input chain, expanding tabs and * noting the presence of special characters as we go. */ void __mkd_enqueue(Document* a, Cstring *line) { Line *p = calloc(sizeof *p, 1); unsigned char c; int xp = 0; int size = S(*line); unsigned char *str = (unsigned char*)T(*line); CREATE(p->text); ATTACH(a->content, p); while ( size-- ) { if ( (c = *str++) == '\t' ) { /* expand tabs into ->tabstop spaces. We use ->tabstop * because the ENTIRE FREAKING COMPUTER WORLD uses editors * that don't do ^T/^D, but instead use tabs for indentation, * and, of course, set their tabs down to 4 spaces */ do { EXPAND(p->text) = ' '; } while ( ++xp % a->tabstop ); } else if ( c >= ' ' ) { if ( c == '|' ) p->flags |= PIPECHAR; EXPAND(p->text) = c; ++xp; } } EXPAND(p->text) = 0; S(p->text)--; p->dle = mkd_firstnonblank(p); } /* trim leading blanks from a header line */ void __mkd_header_dle(Line *p) { CLIP(p->text, 0, 1); p->dle = mkd_firstnonblank(p); } /* build a Document from any old input. */ typedef int (*getc_func)(void*); Document * populate(getc_func getc, void* ctx, int flags) { Cstring line; Document *a = __mkd_new_Document(); int c; int pandoc = 0; if ( !a ) return 0; a->tabstop = (flags & MKD_TABSTOP) ? 4 : TABSTOP; CREATE(line); while ( (c = (*getc)(ctx)) != EOF ) { if ( c == '\n' ) { if ( pandoc != EOF && pandoc < 3 ) { if ( S(line) && (T(line)[0] == '%') ) pandoc++; else pandoc = EOF; } __mkd_enqueue(a, &line); S(line) = 0; } else if ( isprint(c) || isspace(c) || (c & 0x80) ) EXPAND(line) = c; } if ( S(line) ) __mkd_enqueue(a, &line); DELETE(line); if ( (pandoc == 3) && !(flags & (MKD_NOHEADER|MKD_STRICT)) ) { /* the first three lines started with %, so we have a header. * clip the first three lines out of content and hang them * off header. */ Line *headers = T(a->content); a->title = headers; __mkd_header_dle(a->title); a->author= headers->next; __mkd_header_dle(a->author); a->date = headers->next->next; __mkd_header_dle(a->date); T(a->content) = headers->next->next->next; } return a; } /* convert a file into a linked list */ Document * mkd_in(FILE *f, DWORD flags) { return populate((getc_func)fgetc, f, flags & INPUT_MASK); } /* return a single character out of a buffer */ int __mkd_io_strget(struct string_stream *in) { if ( !in->size ) return EOF; --(in->size); return *(in->data)++; } /* convert a block of text into a linked list */ Document * mkd_string(const char *buf, int len, DWORD flags) { struct string_stream about; about.data = buf; about.size = len; return populate((getc_func)__mkd_io_strget, &about, flags & INPUT_MASK); } /* write the html to a file (xmlified if necessary) */ int mkd_generatehtml(Document *p, FILE *output) { char *doc; int szdoc; if ( (szdoc = mkd_document(p, &doc)) != EOF ) { if ( p->ctx->flags & MKD_CDATA ) mkd_generatexml(doc, szdoc, output); else fwrite(doc, szdoc, 1, output); putc('\n', output); return 0; } return -1; } /* convert some markdown text to html */ int markdown(Document *document, FILE *out, int flags) { if ( mkd_compile(document, flags) ) { mkd_generatehtml(document, out); mkd_cleanup(document); return 0; } return -1; } /* write out a Cstring, mangled into a form suitable for `0) && !isalpha(line[0]) ) (*outchar)('L',out); for ( i=0; i < size ; i++ ) { c = line[i]; if ( labelformat ) { if ( isalnum(c) || (c == '_') || (c == ':') || (c == '-') || (c == '.' ) ) (*outchar)(c, out); else (*outchar)('.', out); } else (*outchar)(c,out); } if (line) free(line); } /* ___mkd_reparse() a line */ static void mkd_parse_line(char *bfr, int size, MMIOT *f, int flags) { ___mkd_initmmiot(f, 0); f->flags = flags & USER_FLAGS; ___mkd_reparse(bfr, size, 0, f, 0); ___mkd_emblock(f); } /* ___mkd_reparse() a line, returning it in malloc()ed memory */ int mkd_line(char *bfr, int size, char **res, DWORD flags) { MMIOT f; int len; mkd_parse_line(bfr, size, &f, flags); if ( len = S(f.out) ) { /* kludge alert; we know that T(f.out) is malloced memory, * so we can just steal it away. This is awful -- there * should be an opaque method that transparently moves * the pointer out of the embedded Cstring. */ EXPAND(f.out) = 0; *res = T(f.out); T(f.out) = 0; S(f.out) = ALLOCATED(f.out) = 0; } else { *res = 0; len = EOF; } ___mkd_freemmiot(&f, 0); return len; } /* ___mkd_reparse() a line, writing it to a FILE */ int mkd_generateline(char *bfr, int size, FILE *output, DWORD flags) { MMIOT f; mkd_parse_line(bfr, size, &f, flags); if ( flags & MKD_CDATA ) mkd_generatexml(T(f.out), S(f.out), output); else fwrite(T(f.out), S(f.out), 1, output); ___mkd_freemmiot(&f, 0); return 0; } /* set the url display callback */ void mkd_e_url(Document *f, mkd_callback_t edit) { if ( f ) f->cb.e_url = edit; } /* set the url options callback */ void mkd_e_flags(Document *f, mkd_callback_t edit) { if ( f ) f->cb.e_flags = edit; } /* set the url display/options deallocator */ void mkd_e_free(Document *f, mkd_free_t dealloc) { if ( f ) f->cb.e_free = dealloc; } /* set the url display/options context data field */ void mkd_e_data(Document *f, void *data) { if ( f ) f->cb.e_data = data; } /* set the href prefix for markdown extra style footnotes */ void mkd_ref_prefix(Document *f, char *data) { if ( f ) f->ref_prefix = data; } discount-2.1.7/mkdio.h.in000066400000000000000000000075431222516442300152440ustar00rootroot00000000000000#ifndef _MKDIO_D #define _MKDIO_D #include typedef void MMIOT; typedef @DWORD@ mkd_flag_t; /* line builder for markdown() */ MMIOT *mkd_in(FILE*,mkd_flag_t); /* assemble input from a file */ MMIOT *mkd_string(const char*,int,mkd_flag_t); /* assemble input from a buffer */ /* line builder for github flavoured markdown */ MMIOT *gfm_in(FILE*,mkd_flag_t); /* assemble input from a file */ MMIOT *gfm_string(const char*,int,mkd_flag_t); /* assemble input from a buffer */ void mkd_basename(MMIOT*,char*); void mkd_initialize(); void mkd_with_html5_tags(); void mkd_shlib_destructor(); /* compilation, debugging, cleanup */ int mkd_compile(MMIOT*, mkd_flag_t); void mkd_cleanup(MMIOT*); /* markup functions */ int mkd_dump(MMIOT*, FILE*, int, char*); int markdown(MMIOT*, FILE*, mkd_flag_t); int mkd_line(char *, int, char **, mkd_flag_t); typedef int (*mkd_sta_function_t)(const int,const void*); void mkd_string_to_anchor(char *, int, mkd_sta_function_t, void*, int); int mkd_xhtmlpage(MMIOT*,int,FILE*); /* header block access */ char* mkd_doc_title(MMIOT*); char* mkd_doc_author(MMIOT*); char* mkd_doc_date(MMIOT*); /* compiled data access */ int mkd_document(MMIOT*, char**); int mkd_toc(MMIOT*, char**); int mkd_css(MMIOT*, char **); int mkd_xml(char *, int, char **); /* write-to-file functions */ int mkd_generatehtml(MMIOT*,FILE*); int mkd_generatetoc(MMIOT*,FILE*); int mkd_generatexml(char *, int,FILE*); int mkd_generatecss(MMIOT*,FILE*); #define mkd_style mkd_generatecss int mkd_generateline(char *, int, FILE*, mkd_flag_t); #define mkd_text mkd_generateline /* url generator callbacks */ typedef char * (*mkd_callback_t)(const char*, const int, void*); typedef void (*mkd_free_t)(char*, void*); void mkd_e_url(void *, mkd_callback_t); void mkd_e_flags(void *, mkd_callback_t); void mkd_e_free(void *, mkd_free_t ); void mkd_e_data(void *, void *); /* version#. */ extern char markdown_version[]; void mkd_mmiot_flags(FILE *, MMIOT *, int); void mkd_flags_are(FILE*, mkd_flag_t, int); void mkd_ref_prefix(MMIOT*, char*); /* special flags for markdown() and mkd_text() */ #define MKD_NOLINKS 0x00000001 /* don't do link processing, block tags */ #define MKD_NOIMAGE 0x00000002 /* don't do image processing, block */ #define MKD_NOPANTS 0x00000004 /* don't run smartypants() */ #define MKD_NOHTML 0x00000008 /* don't allow raw html through AT ALL */ #define MKD_STRICT 0x00000010 /* disable SUPERSCRIPT, RELAXED_EMPHASIS */ #define MKD_TAGTEXT 0x00000020 /* process text inside an html tag; no * , no , no html or [] expansion */ #define MKD_NO_EXT 0x00000040 /* don't allow pseudo-protocols */ #define MKD_NOEXT MKD_NO_EXT /* ^^^ (aliased for user convenience) */ #define MKD_CDATA 0x00000080 /* generate code for xml ![CDATA[...]] */ #define MKD_NOSUPERSCRIPT 0x00000100 /* no A^B */ #define MKD_NORELAXED 0x00000200 /* emphasis happens /everywhere/ */ #define MKD_NOTABLES 0x00000400 /* disallow tables */ #define MKD_NOSTRIKETHROUGH 0x00000800 /* forbid ~~strikethrough~~ */ #define MKD_TOC 0x00001000 /* do table-of-contents processing */ #define MKD_1_COMPAT 0x00002000 /* compatibility with MarkdownTest_1.0 */ #define MKD_AUTOLINK 0x00004000 /* make http://foo.com link even without <>s */ #define MKD_SAFELINK 0x00008000 /* paranoid check for link protocol */ #define MKD_NOHEADER 0x00010000 /* don't process header blocks */ #define MKD_TABSTOP 0x00020000 /* expand tabs to 4 spaces */ #define MKD_NODIVQUOTE 0x00040000 /* forbid >%class% blocks */ #define MKD_NOALPHALIST 0x00080000 /* forbid alphabetic lists */ #define MKD_NODLIST 0x00100000 /* forbid definition lists */ #define MKD_EXTRA_FOOTNOTE 0x00200000 /* enable markdown extra-style footnotes */ #define MKD_NOSTYLE 0x00400000 /* don't extract ' '' ASK='' try 'multiple lines' "$ASK" '' try 'unclosed' '