pax_global_header00006660000000000000000000000064130653431040014511gustar00rootroot0000000000000052 comment=2a1c5b52fa6846568e72cd635041aee80218a4db discount-2.2.3b8/000077500000000000000000000000001306534310400135775ustar00rootroot00000000000000discount-2.2.3b8/COPYRIGHT000066400000000000000000000027541306534310400151020ustar00rootroot00000000000000->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.2.3b8/CREDITS000066400000000000000000000030311306534310400146140ustar00rootroot00000000000000Discount 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.portland.or.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.2.3b8/Csio.c000066400000000000000000000017641306534310400146500ustar00rootroot00000000000000#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, flags, &f, 0); ___mkd_emblock(&f); SUFFIX(*iot, T(f.out), S(f.out)); ___mkd_freemmiot(&f, 0); } discount-2.2.3b8/INSTALL000066400000000000000000000034721306534310400146360ustar00rootroot00000000000000 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 --with-amalloc Use my paranoid malloc library to catch memory leaks --shared Build shared libraries --debian-glitch When mangling email addresses, do them deterministically so the Debian regression tester won't complain --pkg-config Build & install a pkg-config(1) .pc file for the discount library. --h1-title Have theme & mkd2html use the first h1 in a document as the title if there's no pandoc header or title specified on the command line. 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.2.3b8/Makefile.in000066400000000000000000000126621306534310400156530ustar00rootroot00000000000000CC=@CC@ -I. LFLAGS=-L. CFLAGS=@CFLAGS@ AR=@AR@ RANLIB=@RANLIB@ BINDIR=@exedir@ MANDIR=@mandir@ LIBDIR=@libdir@ INCDIR=@prefix@/include @MK_PKGCONFIG@PKGDIR=$(LIBDIR)/pkgconfig 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@ @H1TITLE@ TESTFRAMEWORK=echo cols branch # modules that markdown, makepage, mkd2html, &tc use COMMON=pgm_options.o gethopt.o notspecial.o 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) $(DESTDIR)$(PKGDIR) @INSTALL_PROGRAM@ $(PGMS) $(DESTDIR)$(BINDIR) ./librarian.sh install libmarkdown VERSION $(DESTDIR)$(LIBDIR) @INSTALL_DATA@ mkdio.h $(DESTDIR)$(INCDIR) @MK_PKGCONFIG@$(DESTDIR)$(PKGDIR)/$(MKDLIB).pc: $(MKDLIB).pc $(DESTDIR)$(PKGDIR) @MK_PKGCONFIG@ @INSTALL_DATA@ $(MKDLIB).pc $(DESTDIR)$(PKGDIR) install.everything: install install.samples install.man install.samples: $(SAMPLE_PGMS) install $(DESTDIR)$(BINDIR) @INSTALL_DIR@ $(DESTDIR)$(MANDIR)/man1 for x in $(SAMPLE_PGMS); do \ @INSTALL_PROGRAM@ $$x $(DESTDIR)$(BINDIR)/$(SAMPLE_PFX)$$x; \ @INSTALL_DATA@ $$x.1 $(DESTDIR)$(MANDIR)/man1/$(SAMPLE_PFX)$$x.1; \ done 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) @MK_PKGCONFIG@$(DESTDIR)$(PKGDIR): @MK_PKGCONFIG@ @INSTALL_DIR@ $(DESTDIR)$(PKGDIR) version.o: version.c VERSION branch $(CC) $(CFLAGS) -DBRANCH=`./branch` -DVERSION=\"`cat VERSION`\" -c version.c VERSION: @true tags.o: tags.c cstring.h tags.h blocktags blocktags: mktags ./mktags > blocktags # example programs @THEME@theme: theme.o $(COMMON) $(MKDLIB) mkdio.h @THEME@ $(CC) $(CFLAGS) $(LFLAGS) -o theme theme.o $(COMMON) -lmarkdown @LIBS@ mkd2html: mkd2html.o $(MKDLIB) mkdio.h gethopt.h $(COMMON) $(CC) $(CFLAGS) $(LFLAGS) -o mkd2html mkd2html.o $(COMMON) -lmarkdown @LIBS@ markdown: main.o $(COMMON) $(MKDLIB) $(CC) $(CFLAGS) $(LFLAGS) -o markdown main.o $(COMMON) -lmarkdown @LIBS@ makepage: makepage.c $(COMMON) $(MKDLIB) mkdio.h $(CC) $(CFLAGS) $(LFLAGS) -o makepage makepage.c $(COMMON) -lmarkdown @LIBS@ pgm_options.o: pgm_options.c mkdio.h config.h $(CC) $(CFLAGS) -I. -c pgm_options.c notspecial.o: notspecial.c $(CC) $(CFLAGS) -I. -c notspecial.c gethopt.o: gethopt.c $(CC) $(CFLAGS) -I. -c gethopt.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 branch: tools/branch.c config.h $(CC) -o branch tools/branch.c 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@ ./mktags ./blocktags ./librarian.sh 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 setup.o: setup.c config.h cstring.h amalloc.h markdown.h github_flavoured.o: github_flavoured.c config.h cstring.h amalloc.h markdown.h gethopt.o: gethopt.c gethopt.h h1title.o: h1title.c markdown.h notspecial.o: notspecial.c config.h discount-2.2.3b8/Plan9/000077500000000000000000000000001306534310400145625ustar00rootroot00000000000000discount-2.2.3b8/Plan9/README.md000066400000000000000000000025061306534310400160440ustar00rootroot00000000000000# *Discount* Markdown compiler on Plan 9 ## Build % CONFIG='--with-tabstops=7' mk config % mk test % mk install % markdown -V markdown: discount X.Y.Z TAB=7 ### Configuration To select features and extensions, `--with-tabstops=7` may be replaced by zero or more of: * `--enable-pandoc-header`: Use pandoc-style header blocks * `--enable-superscript`: `A^B` becomes AB * `--enable-amalloc`: Enable memory allocation debugging * `--with-tabstops=`*N*: Set tabstops to *N* characters (default 4) * `--enable-alpha-list`: Enable `(a)/(b)/(c)` list markers * `--enable-all-features`: Turn on all stable optional features ## Notes 1. This is not a port from POSIX to native Plan 9 APIs. The supplied `mkfile` merely drives Discount's own `configure.sh` through Plan 9's *APE* environment (in *pcc*(1)) to build the Discount source, then copies the result to locations appropriate for system-wide use on Plan 9. 2. 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* in sections 1, 2, and 6. * `install.progs`: Extra programs. *makepage* writes complete XHTML documents, rather than fragments. *mkd2html* is similar, but produces HTML. discount-2.2.3b8/Plan9/markdown.1000066400000000000000000000050701306534310400164700ustar00rootroot00000000000000.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.2.3b8/Plan9/markdown.2000066400000000000000000000125661306534310400165010ustar00rootroot00000000000000.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. .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 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.2.3b8/Plan9/mkfile000066400000000000000000000014341306534310400157560ustar00rootroot00000000000000BIN=/$objtype/bin CC='cc -D_BSD_EXTENSION -D_C99_SNPRINTF_EXTENSION' markdown: ape/psh -c 'cd .. && $CC mktags.c -o mktags && ./mktags > blocktags && 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.2.3b8/README000066400000000000000000000012651306534310400144630ustar00rootroot00000000000000DISCOUNT 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.2.3b8/VERSION000066400000000000000000000000101306534310400146360ustar00rootroot000000000000002.2.3b8 discount-2.2.3b8/amalloc.c000066400000000000000000000051631306534310400153600ustar00rootroot00000000000000/* * debugging malloc()/realloc()/calloc()/free() that attempts * to keep track of just what's been allocated today. */ #include #include #include "config.h" #define MAGIC 0x1f2e3d4c struct alist { int magic, size, index; int *end; struct alist *next, *last; }; static struct alist list = { 0, 0, 0, 0 }; static int mallocs=0; static int reallocs=0; static int frees=0; static int index = 0; static void die(char *msg, int index) { fprintf(stderr, msg, index); abort(); } void * acalloc(int count, int size) { struct alist *ret; if ( size > 1 ) { count *= size; size = 1; } if ( ret = calloc(count + sizeof(struct alist) + sizeof(int), size) ) { ret->magic = MAGIC; ret->size = size * count; ret->index = index ++; ret->end = (int*)(count + (char*) (ret + 1)); *(ret->end) = ~MAGIC; 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 ) { if ( ! (p2->end && *(p2->end) == ~MAGIC) ) die("goddam: corrupted memory block %d in free()!\n", p2->index); 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 ) { if ( ! (p2->end && *(p2->end) == ~MAGIC) ) die("goddam: corrupted memory block %d in realloc()!\n", p2->index); save.next = p2->next; save.last = p2->last; p2 = realloc(p2, sizeof(int) + sizeof(*p2) + size); if ( p2 ) { p2->size = size; p2->end = (int*)(size + (char*) (p2 + 1)); *(p2->end) = ~MAGIC; 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.2.3b8/amalloc.h000066400000000000000000000007541306534310400153660ustar00rootroot00000000000000/* * 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.2.3b8/basename.c000066400000000000000000000015731306534310400155240ustar00rootroot00000000000000/* * 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.2.3b8/configure.inc000077500000000000000000001077121306534310400162660ustar00rootroot00000000000000# @(#) 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 "int 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 int 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 int 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 int 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 int 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 int main() { puts("hello, sailor"); } EOF TLOGN "checking the C compiler" unset AC_CFLAGS AC_LDFLAGS __MACOS_DSYM 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" $AC_CC -o ngc$$ ngc$$.c status=$? 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 # macos-specific(?) test for .dSYM resource directories $AC_CC $AC_CFLAGS $AC_LDFLAGS -o ngc$$ ngc$$.c ls -dl ngc$$* test -d ngc$$.dSYM && __MACOS_DSYM=1 else AC_FAIL " does not compile code properly" fi __remove ngc$$ ngc$$.c ngc$$.o return $status } # # check for the existence of __attribute__((__noreturn__)) # AC_CHECK_NORETURN() { AC_PROG_CC echo "extern int noreturn __attribute__((__noreturn__));" > ngc$$.c TLOGN "Checking __attribute__((__noreturn__)) " if $AC_CC -c ngc$$.c; then TLOG "(yes)" AC_DEFINE 'NORETURN' ' __attribute__((__noreturn__))' else TLOG "(no)" AC_DEFINE 'NORETURN' '' fi } # # 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_CC 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" # --- is this needed anymore? --- # if AC_QUIET AC_CHECK_HEADERS WinDef.h; then # # windows machine; BYTE, WORD, DWORD already # # defined # # for x in $@; do # case "$x" in # sub)AC_SUB DWORD DWORD # AC_SUB WORD WORD # AC_SUB BYTE BYTE # ;; # *) # echo "#include " >> "$__cwd"/config.h # ;; # esac # done # 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 } # # quote a string if it has spaces in it # __ac_quote() { echo "$1" | sed -e 's/ /\\\\ /g' } # # AC_OUTPUT generates makefiles from makefile.in's # AC_OUTPUT () { cd "$__cwd" AC_SUB 'LIBS' "$AC_LIBS" AC_SUB 'CONFIGURE_FILES' "$__config_files" if test "$__MACOS_DSYM"; then # deal with extra OSX droppings, if they exist AC_SUB 'GENERATED_FILES' "-r *.dSYM $*" else AC_SUB 'GENERATED_FILES' "$*" fi AC_SUB 'CC' "$AC_CC" AC_SUB 'CFLAGS' "$AC_CFLAGS" AC_SUB 'LDFLAGS' "$AC_LDFLAGS" AC_SUB 'srcdir' `__ac_quote "$AC_SRCDIR"` AC_SUB 'prefix' `__ac_quote "$AC_PREFIX"` AC_SUB 'exedir' `__ac_quote "$AC_EXECDIR"` AC_SUB 'sbindir' `__ac_quote "$AC_SBINDIR"` AC_SUB 'libdir' `__ac_quote "$AC_LIBDIR"` AC_SUB 'libexec' `__ac_quote "$AC_LIBEXEC"` AC_SUB 'confdir' `__ac_quote "$AC_CONFDIR"` AC_SUB 'mandir' `__ac_quote "$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 __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 int 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 int 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 " (yes, needs -lresolv)" AC_LIBS="$AC_LIBS -lresolv" elif $AC_CC -DBIND_8_COMPAT -o ngc$$ ngc$$.c; then TLOG " (fyes, needs BIND_8_COMPAT)" AC_DEFINE BIND_8_COMPAT 1 elif $AC_CC -DBIND_8_COMPAT -o ngc$$ ngc$$.c -lresolv; then TLOG " (yes, needs BIND_8_COMPAT & -lresolv)" AC_DEFINE BIND_8_COMPAT 1 AC_LIBS="$AC_LIBS -lresolv" 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 int 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*); int main() { char *a = basename("/a/test"); char *b = basename("/a/nother"); if ( a == 0 || b == 0 || a == b ) return 0; 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" EOF test "$LDCONFIG" && echo ' '$LDCONFIG '"$1"' >> librarian.sh cat >> librarian.sh << EOF ;; 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' "./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_config_sed; a C program to do escaping for AC_SUB __ac_config_sed() { test -x config.sed && return echo "generating config.sed" AC_PROG_CC cat > ngc$$.c << \EOF #include int main(argc, argv) int argc; char **argv; { char *p; if (argc != 3) return 1; printf("s;@%s@;", argv[1]); for (p=argv[2]; *p; ++p) { if ( *p == ';' ) putchar('\\'); putchar(*p); } puts(";g"); return 0; } EOF $AC_CC -o config.sed ngc$$.c status=$? rm -f ngc$$.c if [ "$status" -eq 0 ]; then __config_files="$__config_files config.sed" else AC_FAIL "Cannot generate config.sed helper program" fi } # # AC_SUB writes a substitution into config.sub AC_SUB() { _target="$1" shift echo "target=$_target, rest=$*" __ac_config_sed ./config.sed "$_target" "$*" >> "$__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.2.3b8/configure.sh000077500000000000000000000107351306534310400161250ustar00rootroot00000000000000#! /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) --shared Build shared libraries (default is static) --pkg-config Install pkg-config(1) glue files' 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-*) enable=`echo $K | sed -e 's/--ENABLE-//' | tr '-' '_'` echo WITH_${enable}=T ;; --DEBIAN-GLITCH) echo DEBIAN_GLITCH=T ;; --H1-TITLE) echo H1TITLE=T ;; --PKG-CONFIG) echo PKGCONFIG=T ;; esac } VERSION=`cat VERSION` TARGET=markdown . ./configure.inc AC_INIT $TARGET AC_SUB 'PACKAGE_NAME' lib$TARGET AC_SUB 'PACKAGE_VERSION' $VERSION for banned_with in dl fenced-code id-anchor github-tags urlencoded-anchor; do banned_with_variable_ref=\$WITH_`echo "$banned_with" | $AC_UPPERCASE | tr - _` if [ "`eval echo "$banned_with_variable_ref"`" ]; then LOG "Setting theme default --with-$banned_with." fi done # theme wants the old behavior of --with-(foo) # case "`echo "$WITH_DL" | $AC_UPPERCASE`" in EXTRA) THEME_CF="MKD_DLEXTRA|MKD_NODLDISCOUNT";; BOTH) THEME_CF="MKD_DLEXTRA";; esac test "$WITH_FENCED_CODE" && THEME_CF="${THEME_CF:+$THEME_CF|}MKD_FENCEDCODE" AC_DEFINE THEME_CF "$THEME_CF" test "$DEBIAN_GLITCH" && AC_DEFINE 'DEBIAN_GLITCH' 1 AC_PROG_CC AC_CHECK_NORETURN 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 # should we create a .pc for pkg-config & GNU automake # if [ "$PKGCONFIG" ]; then AC_SUB MK_PKGCONFIG '' elif AC_PROG pkg-config || AC_PROG automake ; then PKGCONFIG=true AC_SUB MK_PKGCONFIG '' else AC_SUB MK_PKGCONFIG '#' fi AC_C_VOLATILE AC_C_CONST AC_C_INLINE AC_SCALAR_TYPES sub hdr AC_CHECK_BASENAME AC_CHECK_ALLOCA AC_CHECK_HEADERS sys/types.h pwd.h && AC_CHECK_FUNCS getpwuid AC_CHECK_HEADERS sys/stat.h && AC_CHECK_FUNCS stat 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 if [ "$H1TITLE" ]; then AC_SUB 'H1TITLE' h1title.o AC_DEFINE USE_H1TITLE 1 else AC_SUB 'H1TITLE' '' fi [ "$OS_FREEBSD" -o "$OS_DRAGONFLY" ] || AC_CHECK_HEADERS malloc.h [ "$WITH_PANDOC_HEADER" ] && AC_DEFINE 'PANDOC_HEADER' '1' GENERATE="Makefile version.c mkdio.h" if [ "$PKGCONFIG" ]; then GENERATE="$GENERATE libmarkdown.pc" fi AC_OUTPUT $GENERATE discount-2.2.3b8/css.c000066400000000000000000000027261306534310400145420ustar00rootroot00000000000000/* 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 ) { /* null-terminate, then strdup() into a free()able memory * chunk */ EXPAND(f) = 0; *res = strdup(T(f)); } DELETE(f); return size; } return EOF; } /* dump any embedded styles to a file */ int mkd_generatecss(Document *d, FILE *f) { char *res; int written; int size = mkd_css(d, &res); written = (size > 0) ? fwrite(res,1,size,f) : 0; if ( res ) free(res); return (written == size) ? size : EOF; } discount-2.2.3b8/cstring.h000066400000000000000000000046351306534310400154310ustar00rootroot00000000000000/* 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.2.3b8/docheader.c000066400000000000000000000014521306534310400156630ustar00rootroot00000000000000/* * 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.2.3b8/dumptree.c000066400000000000000000000054601306534310400155750ustar00rootroot00000000000000/* 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); return 0; } return -1; } discount-2.2.3b8/emmatch.c000066400000000000000000000101201306534310400153530ustar00rootroot00000000000000/* 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) * compatible 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.2.3b8/flags.c000066400000000000000000000044331306534310400150430ustar00rootroot00000000000000#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" }, { MKD_NODLDISCOUNT, "!DLDISCOUNT" }, { MKD_DLEXTRA, "DLEXTRA" }, { MKD_FENCEDCODE, "FENCEDCODE" }, { MKD_IDANCHOR, "IDANCHOR" }, { MKD_GITHUBTAGS, "GITHUBTAGS" }, { MKD_URLENCODEDANCHOR, "URLENCODEDANCHOR" }, { MKD_LATEX, "LATEX" }, { MKD_EXPLICITLIST, "EXPLICITLIST" }, }; #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.2.3b8/generate.c000066400000000000000000001141161306534310400155410ustar00rootroot00000000000000/* 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++; } /* * push a character into the generator input buffer */ static void pushc(char c, MMIOT *f) { EXPAND(f->in) = c; } /* look characters ahead of the cursor. */ static inline unsigned int peek(MMIOT *f, int i) { i += (f->isp-1); return (i >= 0) && (i < S(f->in)) ? (unsigned char)T(f->in)[i] : EOF; } /* pull a byte from the input buffer */ static inline unsigned int pull(MMIOT *f) { return ( f->isp < S(f->in) ) ? (unsigned char)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 * (when setting the current cursor position we also need to flush the * last character written cache) */ #define mmiotseek(f,x) ((f->isp = x), (f->last = 0)) #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); pushc(0, &sub); S(sub.in)--; text(&sub); ___mkd_emblock(&sub); Qwrite(T(sub.out), S(sub.out), f); /* inherit the last character printed from the reparsed * text; this way superscripts can work when they're * applied to something embedded in a link */ f->last = sub.last; ___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 == MKD_EOLN ) /* untokenize hard return */ 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->footnotes->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->note), S(f->footnotes->note), 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 ) { #if DEBIAN_GLITCH Qprintf(f, "&#%02d;", *((unsigned char*)(s++)) ); #else Qstring("&#", f); Qprintf(f, COINTOSS() ? "x%02x;" : "%02d;", *((unsigned char*)(s++)) ); #endif } } /* 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]) == MKD_EOLN) /* 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; else if ( ! (c == '/' || (f->flags & MKD_GITHUBTAGS && (c == '-' || c == '_')) || isalnum(c) ) ) 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 ( c & 0x80 ) /* HACK: ignore utf-8 extended characters */ continue; else if ( isspace(c) || strchr("'\"()[]{}<>`", c) || c == MKD_EOLN ) 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 latex with arbitrary 2-character ( $$ .. $$, \[ .. \], \( .. \) * delimiters */ static int mathhandler(MMIOT *f, int e1, int e2) { int i = 0; while(peek(f, ++i) != EOF) { if (peek(f, i) == e1 && peek(f, i+1) == e2) { cputc(peek(f,-1), f); cputc(peek(f, 0), f); while ( i-- > -1 ) cputc(pull(f), f); return 1; } } return 0; } /* 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 MKD_EOLN: 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)) || (f->last == 0) || ((ispunct(f->last) || isspace(f->last)) && f->last != ')') || 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; case '[': case '(': if ( (f->flags & MKD_LATEX) && mathhandler(f, '\\', (c =='(')?')':']') ) break; /* else fall through to default */ 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; case '$': if ( (f->flags & MKD_LATEX) && (peek(f, 1) == '$') ) { pull(f); if ( mathhandler(f, '$', '$') ) break; Qchar('$', f); } /* fall through to default */ default: f->last = c; 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 ( f->flags & MKD_IDANCHOR ) { 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, f->flags); Qchar('"', f); } Qchar('>', f); } else { if ( f->flags & MKD_TOC ) { Qstring("
text->text), S(pp->text->text), (mkd_sta_function_t)Qchar, f, 1, f->flags); Qstring("\">\n", f); } Qprintf(f, "", pp->hnumber); } 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); pushc(MKD_EOLN, f); pushc('\n', f); } else { ___mkd_tidy(&t->text); push(T(t->text), S(t->text), f); if ( t->next ) pushc('\n', 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->footnotes->reference == 0 ) return; Csprintf(&m->out, "\n
\n
\n
    \n"); for ( i=1; i <= m->footnotes->reference; i++ ) { for ( j=0; j < S(m->footnotes->note); j++ ) { t = &T(m->footnotes->note)[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] ) { /* Add a null byte at the end of the generated html, * but pretend it doesn't exist. */ EXPAND(p->ctx->out) = 0; --S(p->ctx->out); } } *res = T(p->ctx->out); return S(p->ctx->out); } return EOF; } discount-2.2.3b8/gethopt.3000066400000000000000000000121721306534310400153400ustar00rootroot00000000000000.\" Copyright (c) 1988, 1991 Regents of the University of California. .\" Copyright (c) 2017 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 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. All advertising materials mentioning features or use of this software .\" must display the following acknowledgement: .\" This product includes software developed by the University of .\" California, Berkeley and its contributors. .\" 4. Neither the name of the University nor the names of its contributors .\" may be used to endorse or promote products derived from this software .\" without specific prior written permission. .\" .\" THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. .\" .Dd Jan 23, 2017 .Dt GETHOPT 3 .Os Mastodon .Sh NAME .Nm gethopt .Nd get option letter or word from argv .Sh SYNOPSIS .Fd #include "gethopt.h" .Bd -literal -compact struct h_opt { int option; char *optword; char optchar; int opthasarg; char *optdesc; } ; .Ed .Ft char* .Fn hoptarg "struct h_context* argctx" .Ft int .Fn hoptind "struct h_context* argctx" .Ft int .Fn hopterr "struct h_context* argctx" "int flag" .Ft char .Fn hoptopt "struct h_context* argctx" .Ft void .Fn hoptset "struct h_context* argctx" "int argc" "char** argv" .Ft struct h_opt* .Fn gethopt "struct h_context* argctx" "struct h_opt* optarray" "int nropts" .Sh DESCRIPTION The .Fn gethopt function gets the next .Em known option word or character from .Fa argctx . An option is .Em known if it has been specified in the array of accepted options .Fa optarray . .Pp The option array .Fa optarray contains records with either an option word, character, or both, a flag saying the option needs an argument, a short description of the option, and an .Va option key (which is there for the convenience of the calling program; .Fn gethopt does not use it in any way.). It does not matter to .Fn getopt if a following argument has leading white space. .Pp On return from .Fn gethopt , .Fn hoptarg returns an option argument, if it is anticipated, and the variable .Fn hoptind contains the index to the next .Fa argv argument for a subsequent call to .Fn gethopt . .Pp .Fn gethopt uses a (semi) opaque data blob to hold the current state, which must be initialized by the .Fn hoptset function. .Pp The .Fn gethopt function returns .Dv HOPTERR if a non-recognized option is encountered, and NULL when it reaches the end of the options on the command line.. .Pp The interpretation of options in the argument list may be cancelled by .Ql - (single dash) or .Ql -- (double dash) which causes .Fn getopt to signal the end of argument processing and return an .Dv NULL . When all options have been processed (i.e., up to the first non-option argument), .Fn gethopt returns .Dv NULL . .Sh DIAGNOSTICS If the .Fn gethopt function encounters a character not found in .Va optarray or detects a missing option argument it returns .Dv HOPTERR (and writes an error message to the .Em stderr if .Fn hopterr is used to turn error reporting on.) .Sh EXAMPLE .Bd -literal -compact struct h_opt opts[] = { { 0, "css", 0, 1, "css file" }, { 1, "header", 0, 1, "header file" }, { 2, 0, 'a', 0, "option a (no arg)" }, { 3, 0, 'b', 1, "option B (with arg)" }, { 4, "help", '?', 0, "help message" }, } ; #define NROPT (sizeof opts/sizeof opts[0]) int main(argc, argv) char **argv; { struct h_opt *ret; struct h_context ctx; hoptset(&ctx, argc, argv); hopterr(&ctx, 1); while (( ret = gethopt(&ctx, opts, NROPT) )) { if ( ret != HOPTERR ) { if ( ret->optword ) printf("%s", ret->optword); else printf("%c", ret->optchar); if ( ret->opthasarg ) { if ( hoptarg(&ctx) ) printf(" = %s", hoptarg(&ctx)); else printf(" with no argument?"); } puts(ret->optdesc ? ret->optdesc : ""); } } argc -= hoptind(&ctx); argv += hoptind(&ctx); .Ed .Sh HISTORY The .Fn gethopt function was a quick hack to replace manually parsing full-word arguments in .Va discount . discount-2.2.3b8/gethopt.c000066400000000000000000000133701306534310400154210ustar00rootroot00000000000000/* * gehopt; options processing with both single-character and whole-word * options both introduced with - */ #include #include #include "gethopt.h" #include "config.h" /* for bzero() macro on systems that don't have it */ void hoptset(ctx, argc, argv) struct h_context *ctx; int argc; char **argv; { bzero(ctx, sizeof *ctx); ctx->argc = argc; ctx->argv = argv; ctx->optind = 1; } char * hoptarg(ctx) struct h_context *ctx; { return ctx->optarg; } int hoptind(ctx) struct h_context *ctx; { return ctx->optind; } char hoptopt(ctx) struct h_context *ctx; { return ctx->optopt; } int hopterr(ctx,val) struct h_context *ctx; { int old = ctx->opterr; ctx->opterr = !!val; return old; } struct h_opt * gethopt(ctx, opts, nropts) struct h_context *ctx; struct h_opt *opts; int nropts; { int i; int dashes; if ( (ctx == 0) || ctx->optend || (ctx->optind >= ctx->argc) ) return 0; ctx->optarg = 0; ctx->optopt = 0; if ( ctx->optchar == 0) { /* check for leading - */ if ( ctx->argv[ctx->optind][0] != '-' ) { /* out of arguments */ ctx->optend = 1; return 0; } if ( ctx->argv[ctx->optind][1] == 0 || strcmp(ctx->argv[ctx->optind], "--") == 0 ) { /* option list finishes with - or -- token */ ctx->optend = 1; ctx->optind++; return 0; } dashes = 1; if ( ctx->argv[ctx->optind][dashes] == '-' ) { /* support GNU-style long option double-dash prefix * (if gethopt is passed an unknown option with a double-dash * prefix, it won't match a word and then the second dash * will be scanned as if it was a regular old single-character * option.) */ dashes = 2; } for ( i=0; i < nropts; i++ ) { if ( ! opts[i].optword ) continue; if (strcmp(opts[i].optword, dashes+(ctx->argv[ctx->optind]) ) == 0 ) { if ( opts[i].opthasarg ) { if ( ctx->argc > ctx->optind ) { ctx->optarg = ctx->argv[ctx->optind+1]; ctx->optind += 2; } else { /* word argument with required arg at end of *command line */ if ( ctx->opterr ) fprintf(stderr, "%s: option requires an argument -- %s\n", ctx->argv[0], opts[i].optword); ctx->optind ++; return HOPTERR; } } else { ctx->optind ++; } return &opts[i]; } } ctx->optchar = 1; } ctx->optopt = ctx->argv[ctx->optind][ctx->optchar++]; if ( !ctx->optopt ) { /* fell off the end of this argument */ ctx->optind ++; ctx->optchar = 0; return gethopt(ctx, opts, nropts); } for ( i=0; ioptopt ) { /* found a single-char option! */ if ( opts[i].opthasarg ) { if ( ctx->argv[ctx->optind][ctx->optchar] ) { /* argument immediately follows this options (-Oc) */ ctx->optarg = &ctx->argv[ctx->optind][ctx->optchar]; ctx->optind ++; ctx->optchar = 0; } else if ( ctx->optind < ctx->argc-1 ) { /* argument is next arg (-O c) */ ctx->optarg = &ctx->argv[ctx->optind+1][0]; ctx->optind += 2; ctx->optchar = 0; } else { /* end of arg string (-O); set optarg to null, return * (should it opterr on me?) */ ctx->optarg = 0; ctx->optind ++; ctx->optchar = 0; if ( ctx->opterr ) fprintf(stderr, "%s: option requires an argument -- %c\n", ctx->argv[0], opts[i].optchar); return HOPTERR; } } else { if ( !ctx->argv[ctx->optind][ctx->optchar] ) { ctx->optind ++; ctx->optchar = 0; } } return &opts[i]; } } if ( ctx->opterr ) fprintf(stderr, "%s: illegal option -- %c\n", ctx->argv[0], ctx->optopt); return HOPTERR; } void hoptusage(char *pgm, struct h_opt opts[], int nropts, char *arguments) { int i; int optcount; fprintf(stderr, "usage: %s", pgm); /* print out the options that don't have flags first */ for ( optcount=i=0; i < nropts; i++ ) { if ( opts[i].optchar && !opts[i].opthasarg) { if (optcount == 0 ) fputs(" [-", stderr); fputc(opts[i].optchar, stderr); optcount++; } } if ( optcount ) fputc(']', stderr); /* print out the options WITH flags */ for ( i = 0; i < nropts; i++ ) if ( opts[i].optchar && opts[i].opthasarg) fprintf(stderr, " [-%c %s]", opts[i].optchar, opts[i].opthasarg); /* print out the long options */ for ( i = 0; i < nropts; i++ ) if ( opts[i].optword ) { fprintf(stderr, " [-%s", opts[i].optword); if ( opts[i].opthasarg ) fprintf(stderr, " %s", opts[i].opthasarg); fputc(']', stderr); } /* print out the arguments string, if any */ if ( arguments ) fprintf(stderr, " %s", arguments); /* and we're done */ fputc('\n', stderr); } #if DEBUG struct h_opt opts[] = { { 0, "css", 0, 1, "css file" }, { 1, "header", 0, 1, "header file" }, { 2, 0, 'a', 0, "option a (no arg)" }, { 3, 0, 'b', 1, "option B (with arg)" }, { 4, "help", '?', 0, "help message" }, } ; #define NROPT (sizeof opts/sizeof opts[0]) int main(argc, argv) char **argv; { struct h_opt *ret; struct h_context ctx; int i; hoptset(&ctx, argc, argv); hopterr(&ctx, 1); while (( ret = gethopt(&ctx, opts, NROPT) )) { if ( ret != HOPTERR ) { if ( ret->optword ) printf("%s", ret->optword); else printf("%c", ret->optchar); if ( ret->opthasarg ) { if ( hoptarg(&ctx) ) printf(" with argument \"%s\"", hoptarg(&ctx)); else printf(" with no argument?"); } printf(" (%s)\n", ret->optdesc); } } argc -= hoptind(&ctx); argv += hoptind(&ctx); for ( i=0; i < argc; i++ ) printf("%d: %s\n", i, argv[i]); return 0; } #endif /*DEBUG*/ discount-2.2.3b8/gethopt.h000066400000000000000000000016261306534310400154270ustar00rootroot00000000000000/* * gethopt; options processing with both single-character and whole-work * options both introduced with - */ #ifndef __GETHOPT_D #define __GETHOPT_D #include #include struct h_opt { int option; char *optword; char optchar; char *opthasarg; char *optdesc; } ; #define HOPTERR ((struct h_opt*)-1) struct h_context { char **argv; int argc; int optchar; int optind; char *optarg; char optopt; int opterr:1; int optend:1; } ; extern char *hoptarg(struct h_context *); extern int hoptind(struct h_context *); extern char hoptopt(struct h_context *); extern void hoptset(struct h_context *, int, char **); extern int hopterr(struct h_context *, int); extern struct h_opt *gethopt(struct h_context *, struct h_opt*, int); extern void hoptusage(char *, struct h_opt*, int, char *); #endif/*__GETHOPT_D*/ discount-2.2.3b8/github_flavoured.c000066400000000000000000000042141306534310400172750ustar00rootroot00000000000000 /* * 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.2.3b8/h1title.c000066400000000000000000000012611306534310400153150ustar00rootroot00000000000000#include #include "markdown.h" static Paragraph * mkd_h1(Paragraph *p) { Paragraph *found; while ( p ) { if ( p->typ == HDR && p->hnumber == 1 ) return p; if ( p->down && (found = mkd_h1(p->down)) ) return found; p = p->next; } return 0; } char * mkd_h1_title(Document *doc, int flags) { Paragraph *title; if (doc && (title = mkd_h1(doc->code)) ) { char *generated; int size; /* assert that a H1 header is one line long, so that's * the only thing needed */ size = mkd_line(T(title->text->text), S(title->text->text), &generated, flags|MKD_TAGTEXT); if ( size ) return generated; } return 0; } discount-2.2.3b8/html5.c000066400000000000000000000007021306534310400147730ustar00rootroot00000000000000/* 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.2.3b8/libmarkdown.pc.in000066400000000000000000000004071306534310400170420ustar00rootroot00000000000000prefix=@prefix@ exec_prefix=@prefix@ libdir=@libdir@ includedir=@prefix@/include Name: @PACKAGE_NAME@ Version: @PACKAGE_VERSION@ Description: C implementation of John Gruber's Markdown markup language Libs: -L${libdir} -lmarkdown @LIBS@ Cflags: -I${includedir} discount-2.2.3b8/main.c000066400000000000000000000124171306534310400146740ustar00rootroot00000000000000/* * 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 "config.h" #include "amalloc.h" #include "pgm_options.h" #include "tags.h" #include "gethopt.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); } struct h_opt opts[] = { { 0, "html5", '5', 0, "recognise html5 block elements" }, { 0, "base", 'b', "url-base", "URL prefix" }, { 0, "debug", 'd', 0, "debugging" }, { 0, "version",'V', 0, "show version info" }, { 0, 0, 'E', "flags", "url flags" }, { 0, 0, 'F', "bitmap", "set/show hex flags" }, { 0, 0, 'f', "{+-}flags", "set/show named flags" }, { 0, 0, 'G', 0, "github flavoured markdown" }, { 0, 0, 'n', 0, "don't write generated html" }, { 0, 0, 's', "text", "format `text`" }, { 0, "style", 'S', 0, "output 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 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.2.3b8/mkd-functions.3000066400000000000000000000101461306534310400164460ustar00rootroot00000000000000.\" .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.2.3b8/mkd-line.3000066400000000000000000000017321306534310400153660ustar00rootroot00000000000000.\" .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.2.3b8/mkd2html.1000066400000000000000000000016711306534310400154100ustar00rootroot00000000000000.\" %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.portland.or.us discount-2.2.3b8/mkd2html.c000066400000000000000000000112601306534310400154650ustar00rootroot00000000000000/* * 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 -css /~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" #include "gethopt.h" char *pgm = "mkd2html"; extern int notspecial(char *filename); #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); } enum { ADD_CSS, ADD_HEADER, ADD_FOOTER }; struct h_opt opts[] = { { ADD_CSS, "css", 0, "url", "Additional css for this page" }, { ADD_HEADER, "header", 0, "header", "Additonal headers for this page" }, { ADD_FOOTER, "footer", 0, "footer", "Additional footers for this page" }, }; #define NROPTS (sizeof opts/sizeof opts[0]) #if USE_H1TITLE extern char* mkd_h1_title(MMIOT *); #endif main(argc, argv) char **argv; { char *h; char *source = 0, *dest = 0; MMIOT *mmiot; int i; FILE *input, *output; STRING(char*) css, headers, footers; struct h_opt *res; struct h_context flags; CREATE(css); CREATE(headers); CREATE(footers); pgm = basename(argv[0]); hoptset(&flags, argc, argv); hopterr(&flags, 1); while ( res = gethopt(&flags, opts, NROPTS) ) { if ( res == HOPTERR ) { hoptusage(argv[0], opts, NROPTS, "source [dest]"); exit(1); } switch ( res->option ) { case ADD_CSS: EXPAND(css) = hoptarg(&flags); break; case ADD_HEADER: EXPAND(headers) = hoptarg(&flags); break; case ADD_FOOTER: EXPAND(footers) = hoptarg(&flags); break; default: fprintf(stderr, "unknown option?\n"); break; } } argc -= hoptind(&flags); argv += hoptind(&flags); switch ( argc ) { char *p, *dot; case 0: input = stdin; output = stdout; break; case 1: case 2: dest = malloc(strlen(argv[argc-1]) + 6); source = malloc(strlen(argv[0]) + 6); if ( !(source && dest) ) fail("out of memory allocating name buffers"); strcpy(source, argv[0]); 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[0], source); } strcpy(dest, source); if ( notspecial(dest) ) { if (( dot = strrchr(dest, '.') )) *dot = 0; strcat(dest, ".html"); } if ( (output = fopen(dest, "w")) == 0 ) fail("can't write to %s", dest); break; default: hoptusage(argv[0], opts, NROPTS, "source [dest]"); 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); #if USE_H1TITLE if ( ! h ) h = mkd_h1_title(mmiot); #endif /* print a header */ fprintf(output, "\n" "\n" "\n" " \n", markdown_version); fprintf(output," \n"); for ( i=0; i < S(css); i++ ) fprintf(output, " \n", T(css)[i]); fprintf(output," "); if ( h ) mkd_generateline(h, strlen(h), output, 0); /* xhtml requires a <title> in the header, even if it doesn't * contain anything */ 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.2.3b8/mkdio.c000066400000000000000000000174051306534310400150550ustar00rootroot00000000000000/* * 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; DO_OR_DIE( szdoc = mkd_document(p,&doc) ); if ( p->ctx->flags & MKD_CDATA ) DO_OR_DIE( mkd_generatexml(doc, szdoc, output) ); else if ( fwrite(doc, szdoc, 1, output) != 1 ) return EOF; DO_OR_DIE( putc('\n', output) ); return 0; } /* 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 ( h4anchor ? (isalnum(c) || (c == '_') || (c == ':') || (c == '.' ) ) : !(isspace(c) || c == '%') ) (*outchar)(c, out); else { if ( c == ' ' ) (*outchar)('-', out); else { (*outchar)(h4anchor ? '-' : '%', out); (*outchar)(hexchars[c >> 4 & 0xf], out); (*outchar)(hexchars[c & 0xf], out); if ( h4anchor ) (*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) ) { EXPAND(f.out) = 0; /* strdup() doesn't use amalloc(), so in an amalloc()ed * build this copies the string safely out of our memory * paranoia arena. In a non-amalloc world, it's a spurious * memory allocation, but it avoids unintentional hilarity * with amalloc() */ *res = strdup(T(f.out)); } 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; int status; mkd_parse_line(bfr, size, &f, flags); if ( flags & MKD_CDATA ) status = mkd_generatexml(T(f.out), S(f.out), output) != EOF; else status = fwrite(T(f.out), S(f.out), 1, output) == S(f.out); ___mkd_freemmiot(&f, 0); return status ? 0 : EOF; } /* set the url display callback */ void mkd_e_url(Document *f, mkd_callback_t edit) { if ( f ) { if ( f->cb.e_url != edit ) f->dirty = 1; f->cb.e_url = edit; } } /* set the url options callback */ void mkd_e_flags(Document *f, mkd_callback_t edit) { if ( f ) { if ( f->cb.e_flags != edit ) f->dirty = 1; f->cb.e_flags = edit; } } /* set the url display/options deallocator */ void mkd_e_free(Document *f, mkd_free_t dealloc) { if ( f ) { if ( f->cb.e_free != dealloc ) f->dirty = 1; f->cb.e_free = dealloc; } } /* set the url display/options context data field */ void mkd_e_data(Document *f, void *data) { if ( f ) { if ( f->cb.e_data != data ) f->dirty = 1; f->cb.e_data = data; } } /* set the href prefix for markdown extra style footnotes */ void mkd_ref_prefix(Document *f, char *data) { if ( f ) { if ( f->ref_prefix != data ) f->dirty = 1; f->ref_prefix = data; } } discount-2.2.3b8/mkdio.h.in000066400000000000000000000107271306534310400154670ustar00rootroot00000000000000#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' '