pax_global_header 0000666 0000000 0000000 00000000064 11065704713 0014516 g ustar 00root root 0000000 0000000 52 comment=8296fcbfd077a767380ab0320e2aaeae60c93c4d
lua-discount-1.2.10.1/ 0000775 0000000 0000000 00000000000 11065704713 0014345 5 ustar 00root root 0000000 0000000 lua-discount-1.2.10.1/LICENSE 0000664 0000000 0000000 00000004702 11065704713 0015355 0 ustar 00root root 0000000 0000000 The core Discount C sources are
Copyright (C) 2007 David Loren Parsons.
The Discount Lua extension sources are
Copyright (C) 2008 A.S. Bradbury.
Copyright (C) 2008 Tim Channon.
All rights reserved.
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation files
(the "Software"), to deal in the Software without restriction,
including without limitation the rights to use, copy, modify, merge,
publish, distribute, sublicence, and/or sell copies of the Software,
and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
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, and in the same place and form as other
copyright, license and disclaimer information.
3. The end-user documentation included with the redistribution, if
any, must include the following acknowledgment:
This product includes software developed by
David Loren Parsons
in the same place and form as other third-party acknowledgments.
Alternately, this acknowledgment may appear in the software
itself, in the same form and location as other such third-party
acknowledgments.
4. Except as contained in this notice, the name of David Loren
Parsons shall not be used in advertising or otherwise to promote
the sale, use or other dealings in this Software without prior
written authorization from David Loren Parsons.
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED 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 LOREN 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.
lua-discount-1.2.10.1/Makefile 0000664 0000000 0000000 00000001277 11065704713 0016014 0 ustar 00root root 0000000 0000000 LIB_NAME= lua-discount
VERSION= 1.2.10.1
# change these to reflect your Lua installation
LUA= /usr
LUAINC= $(LUA)/include
LUALIB= $(LUA)/lib
LUABIN= $(LUA)/bin
# probably no need to change anything below here
CC= gcc
CFLAGS= $(INCS) $(WARN) -O2 -fPIC ${DEFS}
WARN= -Wall
INCS= -I$(LUAINC)
DEFS =
DISCOUNT_OBJS = docheader.o \
dumptree.o \
generate.o \
markdown.o \
mkdio.o \
resource.o
OBJS= $(DISCOUNT_OBJS) ldiscount.o
SOS= discount.so
all: $(SOS)
$(SOS): $(OBJS)
$(CC) -o $@ -shared $(OBJS) $(LIBS)
.PHONY: clean tar
clean:
rm -f $(OBJS) $(SOS) core core.* a.out
tar: clean
git archive --format=tar --prefix=$(LIB_NAME)-$(VERSION)/ $(VERSION) | gzip > $(LIB_NAME)-$(VERSION).tar.gz
lua-discount-1.2.10.1/README.mkd 0000664 0000000 0000000 00000006543 11065704713 0016007 0 ustar 00root root 0000000 0000000 # lua-discount
A binding to [Discount](http://www.pell.portland.or.us/~orc/Code/discount/), a
fast C implementation of the
[Markdown](http://daringfireball.net/projects/markdown) text to HTML markup
system. Discount passes the Markdown test suite.
## Project links
* [Home](http://asbradbury.org/projects/lua-discount/)
* [Download](http://luaforge.net/projects/lua-discount/)
* [Documentation](http://asbradbury.org/projects/lua-discount/#usage)
* [Source](http://github.com/asb/lua-discount/)
## Release history
* lua-discount-1.2.10.1 (2008-09-22)
* Windows is now a supported platform (thanks to contributions from Tim
Channon)
* lua-discount-1.2.10 (2008-09-03)
* update to upstream Discount 1.2.10
* support the `"nohtml"` option, to disable embedded html.
* compile to use relaxed emphasis, meaning underscores don't count when
they're in the middle of a word.
* add some tests
* include results of a simple benchmark in the readme
* lua-discount-1.2.7 (2008-08-03)
* first public release
## See also
* [Discount](http://www.pell.portland.or.us/~orc/Code/discount/)
* [Markdown syntax](http://daringfireball.net/projects/markdown/syntax)
* [markdown.lua](http://www.frykholm.se/files/markdown.lua)
## Performance
Thanks to the underlying Discount implementation, lua-discount is incredibly
fast. Benchmarking markdown.lua 0.32 against lua-discount 1.2.10 by parsing
the [Markdown syntax
document](http://daringfireball.net/projects/markdown/syntax.text) 100 times
gives the following result (all figures are in seconds):
user system total real
lua-discount 0.170000 0.000000 0.170000 0.177374
markdown.lua 48.530000 0.000000 48.530000 48.524910
## [Usage](id:usage)
Note that `require("discount")` returns a single function, which you are
responsible for giving a suitable name. Example:
discount = require("discount")
local markdown_string = [[
# Demonstration
This is a demonstration of lua-discount. Passing the options `"nolinks"`
disables links such as [this](http://example.com).
]]
local html_string = discount(markdown_string, "nolinks")
The `discount` function takes as its first argument the Markdown string to
convert, and for its subsequent arguments takes any combination of the
following strings as options:
=`"nolinks"`=
do not allow `
Homepage:
lua-discount-1.2.10.1/amalloc.h 0000664 0000000 0000000 00000000754 11065704713 0016134 0 ustar 00root root 0000000 0000000 /*
* 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*/
lua-discount-1.2.10.1/bench.lua 0000664 0000000 0000000 00000001106 11065704713 0016125 0 ustar 00root root 0000000 0000000 require("Benchmark")
require('markdown')
discount = require('discount')
local function read_file(fn)
local file = assert(io.open(fn))
local contents = assert(file:read('*a'))
file:close()
return contents
end
local bench = Benchmark:new()
local REPS = 100
local input = read_file("syntax.text")
print("Benchmarking using http://daringfireball.net/projects/markdown/syntax.text\n")
bench:add("lua-discount", function()
for i=1, REPS do
discount(input)
end
end)
bench:add("markdown.lua", function()
for i=1, REPS do
markdown(input)
end
end)
bench:run()
lua-discount-1.2.10.1/config.h 0000664 0000000 0000000 00000000367 11065704713 0015771 0 ustar 00root root 0000000 0000000 #undef USE_AMALLOC
#ifdef WINDOWS
#define strcasecmp stricmp
#define strncasecmp strnicmp
#endif
#define DL_TAG_EXTENSION 1
#define TABSTOP 4
#define COINTOSS() (rand()&1)
#define INITRNG(x) srand((unsigned int)x)
#define RELAXED_EMPHASIS 1
lua-discount-1.2.10.1/cstring.h 0000664 0000000 0000000 00000004220 11065704713 0016165 0 ustar 00root root 0000000 0000000 /* 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
#include "amalloc.h"
/* expandable Pascal-style string.
*/
#define STRING(type) struct { type *text; int size, alloc; }
#define CREATE(x) T(x) = (void*)(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) (x).alloc ? (free(T(x)), S(x) = (x).alloc = 0) \
: ( S(x) = 0 )
#define CLIP(t,i,sz) \
( ((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])), \
S(t) -= (sz)) : -1
#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
/* 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 ATTACH(t, p) ( (t).text ?( ((t).end->next = (p)), ((t).end = (p)) ) \
:( ((t).text = (t).end = (p)) ) )
typedef STRING(char) Cstring;
#endif/*_CSTRING_D*/
lua-discount-1.2.10.1/docheader.c 0000664 0000000 0000000 00000001523 11065704713 0016430 0 ustar 00root root 0000000 0000000 /*
* 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"
#define afterdle(t) (T((t)->text) + (t)->dle)
char *
mkd_doc_title(Document *doc)
{
if ( doc && doc->headers )
return afterdle(doc->headers);
return 0;
}
char *
mkd_doc_author(Document *doc)
{
if ( doc && doc->headers && doc->headers->next )
return afterdle(doc->headers->next);
return 0;
}
char *
mkd_doc_date(Document *doc)
{
if ( doc && doc->headers && doc->headers->next && doc->headers->next->next )
return afterdle(doc->headers->next->next);
return 0;
}
lua-discount-1.2.10.1/dumptree.c 0000664 0000000 0000000 00000005225 11065704713 0016342 0 ustar 00root root 0000000 0000000 /* 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";
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->align )
d += fprintf(f, ", <%s>", Begin[pp->align]);
for (count=0, p=pp->text; p; ++count, (p = p->next) )
;
if ( count )
d += fprintf(f, ", %d line%s", count, (count==1)?"":"s");
d += fprintf(f, "]");
if ( pp->down ) {
pushpfx(d, pp->down->next ? '+' : '-', sp);
dumptree(pp->down, sp, f);
poppfx(sp);
}
else fputc('\n', f);
pp = pp->next;
}
}
int
mkd_dump(Document *doc, FILE *out, int flags, char *title)
{
Stack stack;
if (mkd_compile(doc, flags) ) {
CREATE(stack);
pushpfx(fprintf(out, "%s", title), doc->code->next ? '+' : '-', &stack);
dumptree(doc->code, &stack, out);
DELETE(stack);
mkd_cleanup(doc);
return 0;
}
return -1;
}
lua-discount-1.2.10.1/generate.c 0000664 0000000 0000000 00000061040 11065704713 0016304 0 ustar 00root root 0000000 0000000 /* 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"
/* prefixes for
*/
static char *autoprefix[] = { "http://", "https://", "ftp://", "news://" };
#define SZAUTOPREFIX (sizeof autoprefix / sizeof autoprefix[0])
typedef int (*stfu)(const void*,const void*);
/* forward declarations */
static void code(int, MMIOT*);
static void text(MMIOT *f);
static Paragraph *display(Paragraph*, MMIOT*);
/* externals from markdown.c */
int __mkd_footsort(Footnote *, Footnote *);
/*
* push text into the generator input buffer
*/
static void
push(char *bfr, int size, MMIOT *f)
{
while ( size-- > 0 )
EXPAND(f->in) = *bfr++;
}
/* look characters ahead of the cursor.
*/
static int
peek(MMIOT *f, int i)
{
i += (f->isp-1);
return (i >= 0) && (i < S(f->in)) ? T(f->in)[i] : EOF;
}
/* pull a byte from the input buffer
*/
static int
pull(MMIOT *f)
{
return ( f->isp < S(f->in) ) ? T(f->in)[f->isp++] : EOF;
}
/* return a pointer to the current position in the input buffer.
*/
static char*
cursor(MMIOT *f)
{
return T(f->in) + f->isp;
}
/* return/set the current cursor position
*/
#define mmiotseek(f,x) (f->isp = x)
#define mmiottell(f) (f->isp)
/* move n characters forward ( or -n characters backward) in the input buffer.
*/
static void
shift(MMIOT *f, int i)
{
if (f->isp + i >= 0 )
f->isp += i;
}
/* Qchar()
*/
static void
Qchar(char 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));
}
/* empair()
*/
static int
empair(MMIOT *f, int go, int level)
{
int i;
block *begin, *p;
begin = &T(f->Q)[go];
for (i=go+1; i < S(f->Q); i++) {
p = &T(f->Q)[i];
if ( (p->b_type != bTEXT) && (p->b_count <= 0) )
break;
if ( p->b_type == begin->b_type ) {
if ( p->b_count == level ) /* exact match */
return i-go;
if ( p->b_count > 2 ) /* fuzzy match */
return i-go;
}
}
return EOF;
}
static struct emtags {
char open[10];
char close[10];
int size;
} emtags[] = { { "" , " ", 5 }, { "", " ", 9 } };
static void
emclose(Cstring *s, int level)
{
PREFIX(*s, emtags[level-1].close, emtags[level-1].size);
}
static void
emopen(Cstring *s, int level)
{
SUFFIX(*s, emtags[level-1].open, emtags[level-1].size-1);
}
/* emmatch()
*/
static void
emmatch(MMIOT *f, int go)
{
block *start = &T(f->Q)[go], *end;
int e, e2, i, match;
while ( start->b_count ) {
switch (start->b_count) {
case 2: e = empair(f,go,match=2);
if ( e != EOF ) break;
case 1: e = empair(f,go,match=1); break;
default:
e = empair(f,go,1);
e2= empair(f,go,2);
if ( e == EOF || ((e2 != EOF) && (e2 >= e)) ) {
e = e2;
match = 2;
}
else
match = 1;
}
if ( e != EOF ) {
end = &T(f->Q)[go+e];
emclose(&end->b_post, match);
emopen(&start->b_text, match);
end->b_count -= match;
}
else {
for (i=0; i < match; i++)
EXPAND(start->b_text) = start->b_char;
}
start->b_count -= match;
}
}
/* emblock()
*/
static void
emblock(MMIOT *f)
{
int i;
block *p;
for (i=0; i < S(f->Q); i++) {
p = &T(f->Q)[i];
if ( p->b_type != bTEXT ) emmatch(f, i);
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;
}
/* generate html from a markup fragment
*/
static void
reparse(char *bfr, int size, int flags, MMIOT *f)
{
MMIOT sub;
___mkd_initmmiot(&sub, f->footnotes);
sub.flags = f->flags | flags;
sub.base = f->base;
push(bfr, size, &sub);
EXPAND(sub.in) = 0;
S(sub.in)--;
text(&sub);
emblock(&sub);
Qwrite(T(sub.out), S(sub.out), f);
___mkd_freemmiot(&sub, f->footnotes);
}
/*
* write out a url, escaping problematic characters
*/
static void
puturl(char *s, int size, MMIOT *f)
{
unsigned char c;
while ( size-- > 0 ) {
c = *s++;
if ( c == '&' )
Qstring("&", f);
else if ( c == '<' )
Qstring("<", f);
else if ( isalnum(c) || c == '.' || c == '-' || c == '_' || c == '/'
|| c == '=' || c == '?' || c == ':' || c == '#' )
Qchar(c, 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 == in )
++indent;
else if ( c == out )
--indent;
}
return size-1;
}
/* extract a []-delimited label from the input stream.
*/
static char *
linkylabel(MMIOT *f, int *sizep)
{
char *ptr = cursor(f);
if ( (*sizep = parenthetical('[',']',f)) != EOF )
return ptr;
return 0;
}
/* 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 ')' or
* whitespace.
*/
static char*
linkyurl(MMIOT *f, int *sizep)
{
int size = 0;
char *ptr;
int c;
if ( (c = eatspace(f)) == EOF )
return 0;
ptr = cursor(f);
if ( c == '<' ) {
pull(f);
ptr++;
if ( (size = parenthetical('<', '>', f)) == EOF )
return 0;
}
else {
for ( ; ((c=pull(f)) != ')') && !isspace(c); size++)
if ( c == EOF ) return 0;
if ( c == ')' )
shift(f, -1);
}
*sizep = size;
return ptr;
}
/* extract a =HHHxWWW size from the input stream
*/
static int
linkysize(MMIOT *f, int *heightp, int *widthp)
{
int height=0, width=0;
int c;
*heightp = 0;
*widthp = 0;
if ( (c = eatspace(f)) != '=' )
return (c != EOF);
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 ( c != EOF ) {
if ( !isspace(c) ) shift(f, -1);
*heightp = height;
*widthp = width;
return 1;
}
}
return 0;
}
/* extract a )-terminated title from the input stream.
*/
static char*
linkytitle(MMIOT *f, int *sizep)
{
int countq=0, qc, c, size;
char *ret, *lastqc = 0;
eatspace(f);
if ( (qc=pull(f)) != '"' && qc != '\'' && qc != '(' )
return 0;
if ( qc == '(' ) qc = ')';
for ( ret = cursor(f); (c = pull(f)) != EOF; ) {
if ( (c == ')') && countq ) {
size = (lastqc ? lastqc : cursor(f)) - ret;
*sizep = size-1;
return ret;
}
else if ( c == qc ) {
lastqc = cursor(f);
countq++;
}
}
return 0;
}
/* look up (or construct) a footnote from the [xxx] link
* at the head of the stream.
*/
static int
linkykey(int image, Footnote *val, MMIOT *f)
{
Footnote *ret;
Cstring mylabel;
memset(val, 0, sizeof *val);
if ( (T(val->tag) = linkylabel(f, &S(val->tag))) == 0 )
return 0;
eatspace(f);
switch ( pull(f) ) {
case '(':
/* embedded link */
if ( (T(val->link) = linkyurl(f,&S(val->link))) == 0 )
return 0;
if ( image && !linkysize(f, &val->height, &val->width) )
return 0;
T(val->title) = linkytitle(f, &S(val->title));
return peek(f,0) == ')';
case '[':
/* footnote link */
mylabel = val->tag;
if ( (T(val->tag) = linkylabel(f, &S(val->tag))) == 0 )
return 0;
if ( !S(val->tag) )
val->tag = mylabel;
ret = bsearch(val, T(*f->footnotes), S(*f->footnotes),
sizeof *val, (stfu)__mkd_footsort);
if ( ret ) {
val->tag = mylabel;
val->link = ret->link;
val->title = ret->title;
val->height = ret->height;
val->width = ret->width;
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 */
} linkytype;
static linkytype imaget = { 0, 0, " ", DENY_IMG|INSIDE_TAG };
static linkytype linkt = { 0, 0, "", " ", DENY_A };
/*
* pseudo-protocols for [][];
*
* id: generates tag
* class: generates tag
* raw: just dump the link without any processing
*/
static linkytype specials[] = {
{ "id:", 3, "", " ", 0 },
{ "class:", 6, "", " ", 0 },
{ "raw:", 4, 0, 0, 0, 0, 0, 0 },
} ;
#define NR(x) (sizeof x / sizeof x[0])
/* see if t contains one of our pseudo-protocols.
*/
static linkytype *
extratag(Cstring t)
{
int i;
linkytype *r;
for ( i=0; i < NR(specials); i++ ) {
r = &specials[i];
if ( (S(t) > r->szpat) && (strncasecmp(T(t), r->pat, r->szpat) == 0) )
return r;
}
return 0;
}
/*
* process embedded links and images
*/
static int
linkylinky(int image, MMIOT *f)
{
int start = mmiottell(f);
Footnote link;
linkytype *tag;
if ( !linkykey(image, &link, f) ) {
mmiotseek(f, start);
return 0;
}
if ( image )
tag = &imaget;
else if ( (f->flags & NO_PSEUDO_PROTO) || (tag = extratag(link.link)) == 0 )
tag = &linkt;
if ( f->flags & tag-> flags ) {
mmiotseek(f, start);
return 0;
}
if ( tag->link_pfx ) {
Qstring(tag->link_pfx, f);
if ( f->base && (T(link.link)[tag->szpat] == '/') )
puturl(f->base, strlen(f->base), f);
puturl(T(link.link) + tag->szpat, S(link.link) - tag->szpat, f);
Qstring(tag->link_sfx, f);
if ( tag->WxH && link.height && link.width ) {
Qprintf(f," height=\"%d\"", link.height);
Qprintf(f, " width=\"%d\"", link.width);
}
if ( S(link.title) ) {
Qstring(" title=\"", f);
reparse(T(link.title), S(link.title), INSIDE_TAG, f);
Qchar('"', f);
}
Qstring(tag->text_pfx, f);
reparse(T(link.tag), S(link.tag), tag->flags, f);
Qstring(tag->text_sfx, f);
}
else
Qwrite(T(link.link) + tag->szpat, S(link.link) - tag->szpat, f);
return 1;
}
/* write a character to output, doing text escapes ( & -> &,
* > -> > < -> < )
*/
static void
cputc(int c, MMIOT *f)
{
switch (c) {
case '&': Qstring("&", f); break;
case '>': Qstring(">", f); break;
case '<': Qstring("<", f); break;
default : Qchar(c, f); break;
}
}
/*
* convert an email address to a string of nonsense
*/
static void
mangle(char *s, int len, MMIOT *f)
{
while ( len-- > 0 ) {
Qstring("", f);
Qprintf(f, COINTOSS() ? "x%02x;" : "%02d;", *((unsigned char*)(s++)) );
}
}
/* before letting a tag through, validate against
* DENY_A and DENY_IMG
*/
static int
forbidden_tag(MMIOT *f)
{
int c = toupper(peek(f, 1));
if ( f->flags & DENY_HTML )
return 1;
if ( c == 'A' && (f->flags & DENY_A) && !isalnum(peek(f,2)) )
return 1;
if ( c == 'I' && (f->flags & DENY_IMG)
&& strncasecmp(cursor(f)+1, "MG", 2) == 0
&& !isalnum(peek(f,4)) )
return 1;
return 0;
}
/* 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)
{
char *text;
int c, size, i;
int maybetag=1, maybeaddress=0;
int mailto;
if ( f->flags & INSIDE_TAG )
return 0;
for ( size=0; ((c = peek(f,size+1)) != '>') && !isspace(c); size++ ) {
if ( ! (c == '/' || isalnum(c) || c == '~') )
maybetag=0;
if ( c == '@' )
maybeaddress=1;
else if ( c == EOF )
return 0;
}
if ( size == 0 )
return 0;
if ( maybetag || (size >= 3 && strncmp(cursor(f), "!--", 3) == 0) ) {
Qstring(forbidden_tag(f) ? "<" : "<", f);
while ( ((c = peek(f, 1)) != EOF) && (c != '>') )
cputc(pull(f), f);
return 1;
}
if ( f->flags & DENY_A ) return 0;
text = cursor(f);
shift(f, size+1);
for ( i=0; i < SZAUTOPREFIX; i++ )
if ( strncasecmp(text, autoprefix[i], strlen(autoprefix[i])) == 0 ) {
Qstring("", f);
puturl(text,size,f);
Qstring(" ", f);
return 1;
}
if ( maybeaddress ) {
Qstring(" 7) && strncasecmp(text, "mailto:", 7) == 0 )
mailto = 7;
else {
mailto = 0;
/* supply a mailto: protocol if one wasn't attached */
mangle("mailto:", 7, f);
}
mangle(text, size, f);
Qstring("\">", f);
mangle(text+mailto, size-mailto, f);
Qstring(" ", f);
return 1;
}
shift(f, -(size+1));
return 0;
} /* maybe_tag_or_link */
static int
isthisspace(MMIOT *f, int i)
{
int c = peek(f, i);
return isspace(c) || (c == EOF);
}
static int
isthisnonword(MMIOT *f, int i)
{
return isthisspace(f, i) || ispunct(peek(f,i));
}
/* 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 },
{ '-', "--", "mdash", 1 },
{ '-', "<->", "ndash", 0 },
{ '.', "...", "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 & DENY_SMARTY )
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);
reparse(cursor(f)+1, j-2, 0, f);
Qstring("”", f);
shift(f,j+1);
return 1;
}
else ++j;
}
}
break;
}
return 0;
} /* smartypants */
#define tag_text(f) (f->flags & INSIDE_TAG)
static void
text(MMIOT *f)
{
int c, j;
int rep;
int smartyflags = 0;
while ( (c = pull(f)) != EOF ) {
if ( smartypants(c, &smartyflags, f) )
continue;
switch (c) {
case 0: 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;
#if SUPERSCRIPT
case '^': if ( isthisspace(f,-1) || isthisspace(f,1) )
Qchar(c,f);
else {
char *sup = cursor(f);
int len = 0;
Qstring("",f);
while ( !isthisspace(f,1+len) ) {
++len;
}
shift(f,len);
reparse(sup, len, 0, f);
Qstring(" ", f);
}
break;
#endif
case '_':
#if RELAXED_EMPHASIS
/* If RELAXED_EMPHASIS, underscores don't count when
* they're in the middle of a word.
*/
if ( (isthisspace(f,-1) && isthisspace(f,1))
|| (isalnum(peek(f,-1)) && isalnum(peek(f,1))) ) {
Qchar(c, f);
break;
}
/* else fall into the regular old emphasis case */
#endif
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 ( tag_text(f) )
Qchar(c, f);
else {
Qstring("", f);
if ( peek(f, 1) == '`' ) {
pull(f);
code(2, f);
}
else
code(1, f);
Qstring("
", f);
}
break;
case '\\': switch ( c = pull(f) ) {
case '&': Qstring("&", f);
break;
case '<': Qstring("<", f);
break;
case '\\':
case '>': case '#': case '.': case '-':
case '+': case '{': case '}': case ']':
case '(': case ')': case '"': case '\'':
case '!': case '[': case '*': case '_':
case '`': Qchar(c, f);
break;
default:
Qchar('\\', f);
if ( c != EOF )
shift(f,-1);
break;
}
break;
case '<': if ( !maybe_tag_or_link(f) )
Qstring("<", f);
break;
case '&': j = (peek(f,1) == '#' ) ? 2 : 1;
while ( isalnum(peek(f,j)) )
++j;
if ( peek(f,j) != ';' )
Qstring("&", f);
else
Qchar(c, f);
break;
default: Qchar(c, f);
break;
}
}
} /* text */
static int
endofcode(int escape, int offset, MMIOT *f)
{
switch (escape) {
case 2: if ( peek(f, offset+1) == '`' ) {
shift(f,1);
case 1: shift(f,offset);
return 1;
}
default:return 0;
}
}
/* the only characters that have special meaning in a code block are
* `<' and `&' , which are /always/ expanded to < and &
*/
static void
code(int escape, MMIOT *f)
{
int c;
if ( escape && (peek(f,1) == ' ') )
shift(f,1);
while ( (c = pull(f)) != EOF ) {
switch (c) {
case ' ': if ( peek(f,1) == '`' && endofcode(escape, 1, f) )
return;
Qchar(c, f);
break;
case '`': if ( endofcode(escape, 0, f) )
return;
Qchar(c, f);
break;
case '\\': cputc(c, f);
if ( peek(f,1) == '>' || (c = pull(f)) == EOF )
break;
default: cputc(c, f);
break;
}
}
} /* code */
/* print a header block
*/
static void
printheader(Paragraph *pp, MMIOT *f)
{
Qprintf(f, "", pp->hnumber);
push(T(pp->text->text), S(pp->text->text), f);
text(f);
Qprintf(f, " ", pp->hnumber);
}
static int
printblock(Paragraph *pp, MMIOT *f)
{
Line *t = pp->text;
static char *Begin[] = { "", "", "
" };
static char *End[] = { "", "
","" };
while (t) {
if ( S(t->text) ) {
if ( S(t->text) > 2 && T(t->text)[S(t->text)-2] == ' '
&& T(t->text)[S(t->text)-1] == ' ') {
push(T(t->text), S(t->text)-2, f);
push(" \n", 6, f);
}
else {
push(T(t->text), S(t->text), f);
if ( t->next )
push("\n", 1, f);
}
}
t = t->next;
}
Qstring(Begin[pp->align], f);
text(f);
Qstring(End[pp->align], f);
return 1;
}
static void
printcode(Line *t, MMIOT *f)
{
int blanks;
for ( blanks = 0; t ; t = t->next )
if ( S(t->text) > t->dle ) {
while ( blanks ) {
push("\n", 1, f);
--blanks;
}
push(T(t->text), S(t->text), f);
push("\n", 1, f);
}
else blanks++;
Qstring("", f);
code(0, f);
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, MMIOT *f)
{
emblock(f);
if ( block ) Qprintf(f, "<%s>", block);
emblock(f);
while (( p = display(p, f) )) {
emblock(f);
Qstring("\n\n", f);
}
if ( block ) Qprintf(f, "%s>", block);
emblock(f);
}
#if DL_TAG_EXTENSION
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);
reparse(T(tag->text), S(tag->text), 0, f);
Qstring(" \n", f);
}
htmlify(p->down, "dd", f);
}
Qstring(" ", f);
}
}
#endif
static void
listdisplay(int typ, Paragraph *p, MMIOT* f)
{
if ( p ) {
Qprintf(f, "<%cl>\n", (typ==UL)?'u':'o');
for ( ; p ; p = p->next ) {
htmlify(p->down, "li", f);
Qchar('\n', f);
}
Qprintf(f, "%cl>\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, f);
break;
case QUOTE:
htmlify(p->down, "blockquote", f);
break;
case UL:
case OL:
listdisplay(p->typ, p->down, f);
break;
#if DL_TAG_EXTENSION
case DL:
definitionlist(p->down, f);
break;
#endif
case HR:
Qstring(" ", f);
break;
case HDR:
printheader(p, f);
break;
default:
printblock(p, f);
break;
}
return p->next;
}
/*
* dump out stylesheet sections.
*/
static int
stylesheets(Paragraph *p, FILE *f)
{
Line* q;
for ( ; p ; p = p->next ) {
if ( p->typ == STYLE ) {
for ( q = p->text; q ; q = q->next )
if ( fwrite(T(q->text), S(q->text), 1, f) == 1 )
putc('\n', f);
else
return EOF;
}
if ( p->down && (stylesheets(p->down, f) == EOF) )
return EOF;
}
return 0;
}
/* return a pointer to the compiled markdown
* document.
*/
int
mkd_document(Document *p, char **res)
{
if ( p && p->compiled ) {
if ( ! p->html ) {
htmlify(p->code, 0, p->ctx);
p->html = 1;
}
*res = T(p->ctx->out);
return S(p->ctx->out);
}
return EOF;
}
/* public interface for reparse()
*/
int
mkd_text(char *bfr, int size, FILE *output, int flags)
{
MMIOT f;
___mkd_initmmiot(&f, 0);
f.flags = flags & USER_FLAGS;
reparse(bfr, size, 0, &f);
emblock(&f);
if ( flags & CDATA_OUTPUT )
___mkd_xml(T(f.out), S(f.out), output);
else
fwrite(T(f.out), S(f.out), 1, output);
___mkd_freemmiot(&f, 0);
return 0;
}
/* dump any embedded styles
*/
int
mkd_style(Document *d, FILE *f)
{
if ( d && d->compiled )
return stylesheets(d->code, f);
return EOF;
}
lua-discount-1.2.10.1/ldiscount.c 0000664 0000000 0000000 00000006021 11065704713 0016514 0 ustar 00root root 0000000 0000000 #include
#include
#include "lua.h"
#include "lauxlib.h"
#include "markdown.h"
/* copied from mkdio.h */
/* special flags for markdown() and mkd_text()
*/
#define MKD_NOLINKS 0x0001 /* don't do link processing, block tags */
#define MKD_NOIMAGE 0x0002 /* don't do image processing, block */
#define MKD_NOPANTS 0x0004 /* don't run smartypants() */
#define MKD_NOHTML 0x0008 /* don't allow raw html through AT ALL */
#define MKD_TAGTEXT 0x0020 /* don't expand `_` and `*` */
#define MKD_NO_EXT 0x0040 /* don't allow pseudo-protocols */
#define MKD_CDATA 0x0080 /* generate code for xml ![CDATA[...]] */
#define MKD_EMBED MKD_NOLINKS|MKD_NOIMAGE|MKD_TAGTEXT
/* special flags for mkd_in() and mkd_string()
*/
#define MKD_NOHEADER 0x0100 /* don't process header blocks */
#define MKD_TABSTOP 0x0200 /* expand tabs to 4 spaces */
static const char *const discount_opts[] = {
"nolinks",
"noimages",
"nopants",
"nohtml",
"tagtext",
"noext",
"cdata",
"embed",
NULL
};
static const int discount_opts_codes[] = {
MKD_NOLINKS,
MKD_NOIMAGE,
MKD_NOPANTS,
MKD_NOHTML,
MKD_TAGTEXT,
MKD_NO_EXT,
MKD_CDATA,
MKD_EMBED
};
/* routines duplicated from markdown source without filesystem access */
/* write output in XML format */
static void local___mkd_xml(char *p, int size, luaL_Buffer *b) {
char c;
while (size-- > 0) {
if (!isascii(c = *p++))
continue;
switch (c) {
case '<': luaL_addlstring(b, "<", 4); break;
case '>': luaL_addlstring(b, ">", 4); break;
case '&': luaL_addlstring(b, "&", 5); break;
case '"': luaL_addlstring(b, """, 6); break;
case '\'':luaL_addlstring(b, "'", 6); break;
default: luaL_addchar(b, c);
}
}
}
/* write the html to a buffer (xmlified if necessary) */
static int local_mkd_generatehtml(Document *p, luaL_Buffer *b) {
char *doc;
int szdoc;
if ((szdoc = mkd_document(p, &doc)) != EOF) {
if (p->ctx->flags & CDATA_OUTPUT)
local___mkd_xml(doc, szdoc, b);
else
luaL_addlstring(b, doc, szdoc);
luaL_addchar(b, '\n');
return 0;
}
return -1;
}
/* convert some markdown text to html. */
static int local_markdown(Document *document, luaL_Buffer *b, int flags) {
if (mkd_compile(document, flags)) {
local_mkd_generatehtml(document, b);
mkd_cleanup(document);
return 0;
}
return -1;
}
static int ldiscount(lua_State *L) {
size_t len;
const char *str = luaL_checklstring(L, 1, &len);
int flags = 0;
int num_args = lua_gettop(L);
luaL_Buffer b;
Document *doc;
int ret, i;
for (i = 2; i <= num_args; i++) {
int opt_index = luaL_checkoption(L, i, NULL, discount_opts);
flags |= discount_opts_codes[opt_index];
}
luaL_buffinit(L, &b);
doc = mkd_string(str, len, MKD_TABSTOP|MKD_NOHEADER);
ret = local_markdown(doc, &b, flags);
luaL_pushresult(&b);
if (ret < 0)
return luaL_error(L, "error in markdown conversion");
return 1;
}
LUALIB_API int luaopen_discount(lua_State *L) {
lua_pushcfunction(L, ldiscount);
return 1;
}
lua-discount-1.2.10.1/lua-discount-dev-1.rockspec 0000664 0000000 0000000 00000001260 11065704713 0021420 0 ustar 00root root 0000000 0000000 package="lua-discount"
version="dev-1"
source = {
url = ""
}
description = {
summary = "Binding to a fast C implementation of the Markdown text-to-html markup system",
homepage = "http://asbradbury.org/projects/lua-discount/",
license = "BSD"
}
dependencies = {
"lua >= 5.1"
}
build = {
type = "builtin",
modules = {
discount = {
"docheader.c",
"dumptree.c",
"generate.c",
"markdown.c",
"mkdio.c",
"resource.c",
"ldiscount.c"
}
},
platforms = {
windows = {
modules = {
discount = {
defines = {"WINDOWS"}
}
}
}
}
}
lua-discount-1.2.10.1/markdown.c 0000664 0000000 0000000 00000040454 11065704713 0016342 0 ustar 00root root 0000000 0000000 /* 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"
/* block-level tags for passing html blocks through the blender
*/
struct kw {
char *id;
int siz;
} ;
#define KW(x) { x, sizeof(x)-1 }
static struct kw blocktags[] = { KW("!--"), KW("STYLE"), KW("SCRIPT"),
KW("ADDRESS"), KW("BDO"), KW("BLOCKQUOTE"),
KW("CENTER"), KW("DFN"), KW("DIV"), KW("H1"),
KW("H2"), KW("H3"), KW("H4"), KW("H5"),
KW("H6"), KW("LISTING"), KW("NOBR"),
KW("UL"), KW("P"), KW("OL"), KW("DL"),
KW("PLAINTEXT"), KW("PRE"), KW("TABLE"),
KW("WBR"), KW("XMP"), KW("HR"), KW("BR") };
#define SZTAGS (sizeof blocktags / sizeof blocktags[0])
#define MAXTAG 11 /* sizeof "BLOCKQUOTE" */
typedef int (*stfu)(const void*,const void*);
typedef ANCHOR(Paragraph) ParagraphRoot;
/* case insensitive string sort (for qsort() and bsearch() of block tags)
*/
static int
casort(struct kw *a, struct kw *b)
{
if ( a->siz != b->siz )
return a->siz - b->siz;
return strncasecmp(a->id, b->id, b->siz);
}
/* case insensitive string sort for Footnote tags.
*/
int
__mkd_footsort(Footnote *a, Footnote *b)
{
int i;
char ac, bc;
if ( S(a->tag) != S(b->tag) )
return S(a->tag) - S(b->tag);
for ( i=0; i < S(a->tag); i++) {
ac = tolower(T(a->tag)[i]);
bc = tolower(T(b->tag)[i]);
if ( isspace(ac) && isspace(bc) )
continue;
if ( ac != bc )
return ac - bc;
}
return 0;
}
/* find the first blank character after position
*/
static int
nextblank(Line *t, int i)
{
while ( (i < S(t->text)) && !isspace(T(t->text)[i]) )
++i;
return i;
}
/* find the next nonblank character after position
*/
static int
nextnonblank(Line *t, int i)
{
while ( (i < S(t->text)) && isspace(T(t->text)[i]) )
++i;
return i;
}
/* find the first nonblank character on the Line.
*/
int
mkd_firstnonblank(Line *p)
{
return nextnonblank(p,0);
}
static int
blankline(Line *p)
{
return ! (p && (S(p->text) > p->dle) );
}
static Line *
skipempty(Line *p)
{
while ( p && (p->dle == S(p->text)) )
p = p->next;
return p;
}
static char *
isopentag(Line *p)
{
int i=0, len;
struct kw key, *ret;
if ( !p ) return 0;
len = S(p->text);
if ( len < 3 || T(p->text)[0] != '<' )
return 0;
/* find how long the tag is so we can check to see if
* it's a block-level tag
*/
for ( i=1; i < len && T(p->text)[i] != '>'
&& T(p->text)[i] != '/'
&& !isspace(T(p->text)[i]); ++i )
;
key.id = T(p->text)+1;
key.siz = i-1;
if ( ret = bsearch(&key,blocktags,SZTAGS,sizeof key, (stfu)casort))
return ret->id;
return 0;
}
static int
selfclose(Line *t, char *tag)
{
char *q = T(t->text);
int siz = strlen(tag);
int i;
if ( strcasecmp(tag, "HR") == 0 || strcasecmp(tag, "BR") == 0 )
/* and are self-closing block-level tags,
*/
return 1;
i = S(t->text) - (siz + 3);
/* we specialcase start and end tags on the same line.
*/
return ( i > 0 ) && (q[i] == '<') && (q[i+1] == '/')
&& (q[i+2+siz] == '>')
&& (strncasecmp(&q[i+2], tag, siz) == 0);
}
static Line *
htmlblock(Paragraph *p, char *tag)
{
Line *t = p->text, *ret;
int closesize;
char close[MAXTAG+4];
if ( selfclose(t, tag) || (strlen(tag) >= MAXTAG) ) {
ret = t->next;
t->next = 0;
return ret;
}
closesize = sprintf(close, "%s>", tag);
for ( ; t ; t = t->next) {
if ( strncasecmp(T(t->text), close, closesize) == 0 ) {
ret = t->next;
t->next = 0;
return ret;
}
}
return 0;
}
static Line *
comment(Paragraph *p, char *key)
{
Line *t, *ret;
for ( t = p->text; t ; t = t->next) {
if ( strstr(T(t->text), "-->") ) {
ret = t->next;
t->next = 0;
return ret;
}
}
return t;
}
/* footnotes look like ^{0,3}[stuff]: $
*/
static int
isfootnote(Line *t)
{
int i;
if ( ( (i = t->dle) > 3) || (T(t->text)[i] != '[') )
return 0;
for ( ++i; i < S(t->text) ; ++i ) {
if ( T(t->text)[i] == '[' )
return 0;
else if ( T(t->text)[i] == ']' && T(t->text)[i+1] == ':' )
return 1;
}
return 0;
}
static int
isquote(Line *t)
{
return ( T(t->text)[0] == '>' );
}
static int
dashchar(char c)
{
return (c == '*') || (c == '-') || (c == '_');
}
static int
iscode(Line *t)
{
return (t->dle >= 4);
}
static int
ishr(Line *t)
{
int i, count=0;
char dash = 0;
char c;
if ( iscode(t) ) return 0;
for ( i = 0; i < S(t->text); i++) {
c = T(t->text)[i];
if ( (dash == 0) && dashchar(c) )
dash = c;
if ( c == dash ) ++count;
else if ( !isspace(c) )
return 0;
}
return (count >= 3);
}
static int
ishdr(Line *t, int *htyp)
{
int i, j;
/* first check for etx-style ###HEADER###
*/
/* leading run of `#`'s ?
*/
for ( i=0; T(t->text)[i] == '#'; ++i)
;
if ( i ) {
i = nextnonblank(t, i);
j = S(t->text)-1;
while ( (j > i) && (T(t->text)[j] == '#') )
--j;
while ( (j > 1) && isspace(T(t->text)[j]) )
--j;
if ( i < j ) {
*htyp = ETX;
return 1;
}
}
/* then check for setext-style HEADER
* ======
*/
if ( t->next ) {
char *q = T(t->next->text);
if ( (*q == '=') || (*q == '-') ) {
for (i=1; i < S(t->next->text); i++)
if ( q[0] != q[i] )
return 0;
*htyp = SETEXT;
return 1;
}
}
return 0;
}
static int
isdefinition(Line *t)
{
#if DL_TAG_EXTENSION
return t && t->next
&& (S(t->text) > 2)
&& (t->dle == 0)
&& (T(t->text)[0] == '=')
&& (T(t->text)[S(t->text)-1] == '=')
&& ( (t->next->dle >= 4) || isdefinition(t->next) );
#else
return 0;
#endif
}
static int
islist(Line *t, int *trim)
{
int i, j;
char *q;
if ( iscode(t) || blankline(t) || ishdr(t,&i) || ishr(t) )
return 0;
if ( isdefinition(t) ) {
*trim = 4;
return DL;
}
if ( strchr("*-+", T(t->text)[t->dle]) && isspace(T(t->text)[t->dle+1]) ) {
i = nextnonblank(t, t->dle+1);
*trim = (i > 4) ? 4 : i;
return UL;
}
if ( (j = nextblank(t,t->dle)) > t->dle ) {
if ( T(t->text)[j-1] == '.' ) {
strtoul(T(t->text)+t->dle, &q, 10);
if ( (q > T(t->text)+t->dle) && (q == T(t->text) + (j-1)) ) {
j = nextnonblank(t,j);
*trim = j;
return OL;
}
}
}
return 0;
}
static Line *
headerblock(Paragraph *pp, int htyp)
{
Line *ret = 0;
Line *p = pp->text;
int i, j;
switch (htyp) {
case SETEXT:
/* p->text is header, p->next->text is -'s or ='s
*/
pp->hnumber = (T(p->next->text)[0] == '=') ? 1 : 2;
ret = p->next->next;
___mkd_freeLine(p->next);
p->next = 0;
break;
case ETX:
/* p->text is ###header###, so we need to trim off
* the leading and trailing `#`'s
*/
for (i=0; T(p->text)[i] == T(p->text)[0]; i++)
;
pp->hnumber = i;
while ( (i < S(p->text)) && isspace(T(p->text)[i]) )
++i;
CLIP(p->text, 0, i);
for (j=S(p->text); j && (T(p->text)[j-1] == '#'); --j)
;
S(p->text) = j;
ret = p->next;
p->next = 0;
break;
}
return ret;
}
static Line *
codeblock(Paragraph *p)
{
Line *t = p->text, *r;
/* HORRIBLE STANDARDS KLUDGE: the first line of every block
* has trailing whitespace trimmed off.
*/
while ( S(t->text) && isspace(T(t->text)[S(t->text)-1]) )
--S(t->text);
for ( ; t; t = r ) {
CLIP(t->text,0,4);
t->dle = mkd_firstnonblank(t);
if ( !( (r = skipempty(t->next)) && iscode(r)) ) {
___mkd_freeLineRange(t,r);
t->next = 0;
return r;
}
}
return t;
}
static int
centered(Line *first, Line *last)
{
if ( first&&last ) {
int len = S(last->text);
if ( (len > 2) && (strncmp(T(first->text), "->", 2) == 0)
&& (strncmp(T(last->text)+len-2, "<-", 2) == 0) ) {
CLIP(first->text, 0, 2);
S(last->text) -= 2;
return CENTER;
}
}
return 0;
}
static int
endoftextblock(Line *t, int toplevelblock)
{
int z;
if ( blankline(t)||isquote(t)||iscode(t)||ishdr(t,&z)||ishr(t) )
return 1;
/* HORRIBLE STANDARDS KLUDGE: Toplevel paragraphs eat absorb adjacent
* list items, but sublevel blocks behave properly.
*/
return toplevelblock ? 0 : islist(t,&z);
}
static Line *
textblock(Paragraph *p, int toplevel)
{
Line *t, *next;
for ( t = p->text; t ; t = next )
if ( ((next = t->next) == 0) || endoftextblock(next, toplevel) ) {
p->align = centered(p->text, t);
t->next = 0;
return next;
}
return t;
}
/*
* accumulate a blockquote.
*
* one sick horrible thing about blockquotes is that even though
* it just takes ^> to start a quote, following lines, if quoted,
* assume that the prefix is ``>''. This means that code needs
* to be indented *5* spaces from the leading '>', but *4* spaces
* from the start of the line. This does not appear to be
* documented in the reference implementation, but it's the
* way the markdown sample web form at Daring Fireball works.
*/
static Line *
quoteblock(Paragraph *p)
{
Line *t, *q;
int qp;
for ( t = p->text; t ; t = q ) {
if ( isquote(t) ) {
qp = (T(t->text)[1] == ' ') ? 2 : 1;
CLIP(t->text, 0, qp);
t->dle = mkd_firstnonblank(t);
}
if ( !(q = skipempty(t->next)) || ((q != t->next) && !isquote(q)) ) {
___mkd_freeLineRange(t, q);
return q;
}
}
return t;
}
static Paragraph *Pp(ParagraphRoot *, Line *, int);
static Paragraph *compile(Line *, int, MMIOT *);
/*
* pull in a list block. A list block starts with a list marker and
* runs until the next list marker, the next non-indented paragraph,
* or EOF. You do not have to indent nonblank lines after the list
* marker, but multiple paragraphs need to start with a 4-space indent.
*/
static Line *
listitem(Paragraph *p, int indent)
{
Line *t, *q;
int clip = indent;
int z;
for ( t = p->text; t ; t = q) {
CLIP(t->text, 0, clip);
t->dle = mkd_firstnonblank(t);
if ( (q = skipempty(t->next)) == 0 ) {
___mkd_freeLineRange(t,q);
return 0;
}
/* after a blank line, the next block needs to start with a line
* that's indented 4 spaces, but after that the line doesn't
* need any indentation
*/
if ( q != t->next ) {
if (q->dle < 4) {
q = t->next;
t->next = 0;
return q;
}
indent = 4;
}
if ( (q->dle < indent) && (ishr(q) || ishdr(q,&z) || islist(q,&z)) ) {
q = t->next;
t->next = 0;
return q;
}
clip = (q->dle > indent) ? indent : q->dle;
}
return t;
}
static Line *
listblock(Paragraph *top, int trim, MMIOT *f)
{
ParagraphRoot d = { 0, 0 };
Paragraph *p;
Line *q = top->text, *text;
Line *label;
int para = 0;
while (( text = q )) {
if ( top->typ == DL ) {
Line *lp;
for ( lp = label = text; lp ; lp = lp->next ) {
text = lp->next;
CLIP(lp->text, 0, 1);
S(lp->text)--;
if ( !isdefinition(lp->next) )
lp->next = 0;
}
}
else label = 0;
p = Pp(&d, text, LISTITEM);
text = listitem(p, trim);
p->down = compile(p->text, 0, f);
p->text = label;
if ( para && (top->typ != DL) ) p->down->align = PARA;
if ( !(q = skipempty(text)) || (islist(q,&trim) != top->typ) )
break;
if ( para = (q != text) ) {
Line anchor;
anchor.next = text;
___mkd_freeLineRange(&anchor, q);
}
if ( para && (top->typ != DL) ) p->down->align = PARA;
}
top->text = 0;
top->down = T(d);
return text;
}
static int
tgood(char c)
{
switch (c) {
case '\'':
case '"': return c;
case '(': return ')';
}
return 0;
}
/*
* add a new (image or link) footnote to the footnote table
*/
static Line*
addfootnote(Line *p, MMIOT* f)
{
int j, i;
int c;
Line *np = p->next;
Footnote *foot = &EXPAND(*f->footnotes);
CREATE(foot->tag);
CREATE(foot->link);
CREATE(foot->title);
foot->height = foot->width = 0;
for (j=i=p->dle+1; T(p->text)[j] != ']'; j++)
EXPAND(foot->tag) = T(p->text)[j];
EXPAND(foot->tag) = 0;
S(foot->tag)--;
j = nextnonblank(p, j+2);
while ( (j < S(p->text)) && !isspace(T(p->text)[j]) )
EXPAND(foot->link) = T(p->text)[j++];
EXPAND(foot->link) = 0;
S(foot->link)--;
j = nextnonblank(p,j);
if ( T(p->text)[j] == '=' ) {
sscanf(T(p->text)+j, "=%dx%d", &foot->width, &foot->height);
while ( (j < S(p->text)) && !isspace(T(p->text)[j]) )
++j;
j = nextnonblank(p,j);
}
if ( (j >= S(p->text)) && np && np->dle && tgood(T(np->text)[np->dle]) ) {
___mkd_freeLine(p);
p = np;
np = p->next;
j = p->dle;
}
if ( (c = tgood(T(p->text)[j])) ) {
/* Try to take the rest of the line as a comment; read to
* EOL, then shrink the string back to before the final
* quote.
*/
++j; /* skip leading quote */
while ( j < S(p->text) )
EXPAND(foot->title) = T(p->text)[j++];
while ( S(foot->title) && T(foot->title)[S(foot->title)-1] != c )
--S(foot->title);
if ( S(foot->title) ) /* skip trailing quote */
--S(foot->title);
EXPAND(foot->title) = 0;
--S(foot->title);
}
___mkd_freeLine(p);
return np;
}
/*
* allocate a paragraph header, link it to the
* tail of the current document
*/
static Paragraph *
Pp(ParagraphRoot *d, Line *ptr, int typ)
{
Paragraph *ret = calloc(sizeof *ret, 1);
ret->text = ptr;
ret->typ = typ;
return ATTACH(*d, ret);
}
static Line*
consume(Line *ptr, int *eaten)
{
Line *next;
int blanks=0;
for (; ptr && blankline(ptr); ptr = next, blanks++ ) {
next = ptr->next;
___mkd_freeLine(ptr);
}
if ( ptr ) *eaten = blanks;
return ptr;
}
/*
* break a collection of markdown input into
* blocks of lists, code, html, and text to
* be marked up.
*/
static Paragraph *
compile(Line *ptr, int toplevel, MMIOT *f)
{
ParagraphRoot d = { 0, 0 };
Paragraph *p = 0;
char *key;
Line *r;
int para = toplevel;
int hdr_type, list_type, indent;
ptr = consume(ptr, ¶);
while ( ptr ) {
if ( toplevel && !(f->flags & DENY_HTML) && (key = isopentag(ptr)) ) {
p = Pp(&d, ptr, strcmp(key, "STYLE") == 0 ? STYLE : HTML);
if ( strcmp(key, "!--") == 0 )
ptr = comment(p, key);
else
ptr = htmlblock(p, key);
}
else if ( iscode(ptr) ) {
p = Pp(&d, ptr, CODE);
ptr = codeblock(p);
}
else if ( ishr(ptr) ) {
p = Pp(&d, 0, HR);
r = ptr;
ptr = ptr->next;
___mkd_freeLine(r);
}
else if (( list_type = islist(ptr, &indent) )) {
p = Pp(&d, ptr, list_type);
ptr = listblock(p, indent, f);
}
else if ( isquote(ptr) ) {
p = Pp(&d, ptr, QUOTE);
ptr = quoteblock(p);
p->down = compile(p->text, 1, f);
p->text = 0;
}
else if ( ishdr(ptr, &hdr_type) ) {
p = Pp(&d, ptr, HDR);
ptr = headerblock(p, hdr_type);
}
else if ( toplevel && (isfootnote(ptr)) ) {
ptr = consume(addfootnote(ptr, f), ¶);
continue;
}
else {
p = Pp(&d, ptr, MARKUP);
ptr = textblock(p, toplevel);
}
if ( (para||toplevel) && !p->align )
p->align = PARA;
para = toplevel;
ptr = consume(ptr, ¶);
if ( para && !p->align )
p->align = PARA;
}
return T(d);
}
static void
initialize()
{
static int first = 1;
if ( first-- > 0 ) {
first = 0;
INITRNG(time(0));
qsort(blocktags, SZTAGS, sizeof blocktags[0], (stfu)casort);
}
}
/*
* the guts of the markdown() function, ripped out so I can do
* debugging.
*/
/*
* prepare and compile `text`, returning a Paragraph tree.
*/
int
mkd_compile(Document *doc, int flags)
{
if ( !doc )
return 0;
if ( doc->compiled )
return 1;
doc->compiled = 1;
memset(doc->ctx, 0, sizeof(MMIOT) );
doc->ctx->flags = flags & USER_FLAGS;
doc->ctx->base = doc->base;
CREATE(doc->ctx->in);
doc->ctx->footnotes = malloc(sizeof doc->ctx->footnotes[0]);
CREATE(*doc->ctx->footnotes);
initialize();
doc->code = compile(T(doc->content), 1, doc->ctx);
qsort(T(*doc->ctx->footnotes), S(*doc->ctx->footnotes),
sizeof T(*doc->ctx->footnotes)[0],
(stfu)__mkd_footsort);
memset(&doc->content, 0, sizeof doc->content);
return 1;
}
lua-discount-1.2.10.1/markdown.h 0000664 0000000 0000000 00000007312 11065704713 0016343 0 ustar 00root root 0000000 0000000 #ifndef _MARKDOWN_D
#define _MARKDOWN_D
#include "cstring.h"
/* reference-style links (and images) are stored in an array
* of footnotes.
*/
typedef struct footnote {
Cstring tag; /* the tag for the reference link */
Cstring link; /* what this footnote points to */
Cstring title; /* what it's called (TITLE= attribute) */
int height, width; /* dimensions (for image link) */
} Footnote;
/* each input line is read into a Line, which contains the line,
* the offset of the first non-space character [this assumes
* that all tabs will be expanded to spaces!], and a pointer to
* the next line.
*/
typedef struct line {
Cstring text;
struct line *next;
int dle;
} Line;
/* a paragraph is a collection of Lines, with links to the next paragraph
* and (if it's a QUOTE, UL, or OL) to the reparsed contents of this
* paragraph.
*/
typedef struct paragraph {
struct paragraph *next; /* next paragraph */
struct paragraph *down; /* recompiled contents of this paragraph */
struct line *text; /* all the text in this paragraph */
enum { WHITESPACE=0, CODE, QUOTE, MARKUP,
HTML, STYLE, DL, UL, OL, LISTITEM,
HDR, HR } typ;
enum { IMPLICIT=0, PARA, CENTER} align;
int hnumber; /* for typ == HDR */
} Paragraph;
enum { ETX, SETEXT }; /* header types */
typedef struct block {
enum { bTEXT, bSTAR, bUNDER } b_type;
int b_count;
char b_char;
Cstring b_text;
Cstring b_post;
} block;
typedef STRING(block) Qblock;
/* a magic markdown io thing holds all the data structures needed to
* do the backend processing of a markdown document
*/
typedef struct mmiot {
Cstring out;
Cstring in;
Qblock Q;
int isp;
STRING(Footnote) *footnotes;
int flags;
#define DENY_A 0x0001
#define DENY_IMG 0x0002
#define DENY_SMARTY 0x0004
#define DENY_HTML 0x0008
#define INSIDE_TAG 0x0020
#define NO_PSEUDO_PROTO 0x0040
#define CDATA_OUTPUT 0x0080
#define USER_FLAGS 0x00FF
#define EMBEDDED DENY_A|DENY_IMG|NO_PSEUDO_PROTO|CDATA_OUTPUT
char *base;
} MMIOT;
/*
* the mkdio text input functions return a document structure,
* which contains a header (retrieved from the document if
* markdown was configured * with the * --enable-pandoc-header
* and the document begins with a pandoc-style header) and the
* root of the linked list of Lines.
*/
typedef struct document {
Line *headers; /* title -> author(s) -> date */
ANCHOR(Line) content; /* uncompiled text, not valid after compile() */
Paragraph *code; /* intermediate code generated by compile() */
int compiled; /* set after mkd_compile() */
int html; /* set after (internal) htmlify() */
int tabstop; /* for properly expanding tabs (ick) */
MMIOT *ctx; /* backend buffers, flags, and structures */
char *base; /* url basename for url fragments */
} Document;
extern int mkd_firstnonblank(Line *);
extern int mkd_compile(Document *, int);
extern int mkd_document(Document *, char **);
extern int mkd_generatehtml(Document *, FILE *);
extern void mkd_cleanup(Document *);
extern int mkd_text(char *, int, FILE*, int);
extern void mkd_basename(Document*, char *);
extern Document *mkd_in(FILE *, int);
extern Document *mkd_string(char*,int, int);
#define NO_HEADER 0x0100
#define STD_TABSTOP 0x0200
#define INPUT_MASK (NO_HEADER|STD_TABSTOP)
/* internal resource handling functions.
*/
extern void ___mkd_freeLine(Line *);
extern void ___mkd_freeLines(Line *);
extern void ___mkd_freeParagraph(Paragraph *);
extern void ___mkd_freefootnotes(MMIOT *);
extern void ___mkd_initmmiot(MMIOT *, void *);
extern void ___mkd_freemmiot(MMIOT *, void *);
extern void ___mkd_freeLineRange(Line *, Line *);
extern void ___mkd_xml(char *, int, FILE *);
#endif/*_MARKDOWN_D*/
lua-discount-1.2.10.1/mkdio.c 0000664 0000000 0000000 00000010067 11065704713 0015620 0 ustar 00root root 0000000 0000000 /*
* 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
*/
static Document*
new_Document()
{
Document *ret = calloc(sizeof(Document), 1);
if ( ret ) {
if (( ret->ctx = calloc(sizeof(MMIOT), 1) ))
return ret;
free(ret);
}
return 0;
}
/* add a line to the markdown input chain
*/
static void
queue(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 >= ' ' ) {
EXPAND(p->text) = c;
++xp;
}
}
EXPAND(p->text) = 0;
S(p->text)--;
p->dle = mkd_firstnonblank(p);
}
#ifdef PANDOC_HEADER
/* trim leading blanks from a header line
*/
static void
snip(Line *p)
{
CLIP(p->text, 0, 1);
p->dle = mkd_firstnonblank(p);
}
#endif
/* 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 = new_Document();
int c;
#ifdef PANDOC_HEADER
int pandoc = 0;
#endif
if ( !a ) return 0;
a->tabstop = (flags & STD_TABSTOP) ? 4 : TABSTOP;
CREATE(line);
while ( (c = (*getc)(ctx)) != EOF ) {
if ( c == '\n' ) {
#ifdef PANDOC_HEADER
if ( pandoc != EOF && pandoc < 3 ) {
if ( S(line) && (T(line)[0] == '%') )
pandoc++;
else
pandoc = EOF;
}
#endif
queue(a, &line);
S(line) = 0;
}
else
EXPAND(line) = c;
}
if ( S(line) )
queue(a, &line);
DELETE(line);
#ifdef PANDOC_HEADER
if ( (pandoc == 3) && !(flags & NO_HEADER) ) {
/* the first three lines started with %, so we have a header.
* clip the first three lines out of content and hang them
* off header.
*/
a->headers = T(a->content);
T(a->content) = a->headers->next->next->next;
a->headers->next->next->next = 0;
snip(a->headers);
snip(a->headers->next);
snip(a->headers->next->next);
}
#endif
return a;
}
/* convert a file into a linked list
*/
Document *
mkd_in(FILE *f, int flags)
{
return populate((getc_func)fgetc, f, flags & INPUT_MASK);
}
/* return a single character out of a buffer
*/
struct string_ctx {
char *data; /* the unread data */
int size; /* and how much is there? */
} ;
static int
strget(struct string_ctx *in)
{
if ( !in->size ) return EOF;
--(in->size);
return *(in->data)++;
}
/* convert a block of text into a linked list
*/
Document *
mkd_string(char *buf, int len, int flags)
{
struct string_ctx about;
about.data = buf;
about.size = len;
return populate((getc_func)strget, &about, flags & INPUT_MASK);
}
/* write the html to a file (xmlified if necessary)
*/
int
mkd_generatehtml(Document *p, FILE *output)
{
char *doc;
int szdoc;
if ( (szdoc = mkd_document(p, &doc)) != EOF ) {
if ( p->ctx->flags & CDATA_OUTPUT )
___mkd_xml(doc, szdoc, output);
else
fwrite(doc, szdoc, 1, output);
putc('\n', output);
return 0;
}
return -1;
}
/* convert some markdown text to html
*/
int
markdown(Document *document, FILE *out, int flags)
{
if ( mkd_compile(document, flags) ) {
mkd_generatehtml(document, out);
mkd_cleanup(document);
return 0;
}
return -1;
}
void
mkd_basename(Document *document, char *base)
{
if ( document )
document->base = base;
}
lua-discount-1.2.10.1/mkdio.h 0000664 0000000 0000000 00000003066 11065704713 0015626 0 ustar 00root root 0000000 0000000 #ifndef _MKDIO_D
#define _MKDIO_D
#include
typedef void MMIOT;
/* line builder for markdown()
*/
MMIOT *mkd_in(FILE*,int); /* assemble input from a file */
MMIOT *mkd_string(char*,int,int); /* assemble input from a buffer */
void mkd_basename(MMIOT*,char*);
/* compilation, debugging, cleanup
*/
int mkd_compile(MMIOT*, int);
int mkd_generatehtml(MMIOT*,FILE*);
int mkd_cleanup(MMIOT*);
/* markup functions
*/
int mkd_text(char *, int, FILE*, int);
int mkd_style(MMIOT*, FILE*);
int mkd_dump(MMIOT*, FILE*, int, char*);
int markdown(MMIOT*, FILE*, int);
void mkd_basename(MMIOT*,char*);
/* 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**);
/* version#.
*/
extern char markdown_version[];
/* special flags for markdown() and mkd_text()
*/
#define MKD_NOLINKS 0x0001 /* don't do link processing, block tags */
#define MKD_NOIMAGE 0x0002 /* don't do image processing, block */
#define MKD_NOPANTS 0x0004 /* don't run smartypants() */
#define MKD_NOHTML 0x0008 /* don't allow raw html through AT ALL */
#define MKD_TAGTEXT 0x0020 /* don't expand `_` and `*` */
#define MKD_NO_EXT 0x0040 /* don't allow pseudo-protocols */
#define MKD_CDATA 0x0080 /* generate code for xml ![CDATA[...]] */
#define MKD_EMBED MKD_NOLINKS|MKD_NOIMAGE|MKD_TAGTEXT
/* special flags for mkd_in() and mkd_string()
*/
#define MKD_NOHEADER 0x0100 /* don't process header blocks */
#define MKD_TABSTOP 0x0200 /* expand tabs to 4 spaces */
#endif/*_MKDIO_D*/
lua-discount-1.2.10.1/resource.c 0000664 0000000 0000000 00000005567 11065704713 0016355 0 ustar 00root root 0000000 0000000 /* 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"
/* free a (single) line
*/
void
___mkd_freeLine(Line *ptr)
{
DELETE(ptr->text);
free(ptr);
}
/* free a list of lines
*/
void
___mkd_freeLines(Line *p)
{
if (p->next)
___mkd_freeLines(p->next);
___mkd_freeLine(p);
}
/* bye bye paragraph.
*/
void
___mkd_freeParagraph(Paragraph *p)
{
if (p->next)
___mkd_freeParagraph(p->next);
if (p->down)
___mkd_freeParagraph(p->down);
if (p->text)
___mkd_freeLines(p->text);
free(p);
}
/* bye bye footnotes.
*/
void
___mkd_freefootnotes(MMIOT *f)
{
int i;
if ( f->footnotes ) {
for (i=0; i < S(*f->footnotes); i++) {
DELETE(T(*f->footnotes)[i].tag);
DELETE(T(*f->footnotes)[i].link);
DELETE(T(*f->footnotes)[i].title);
}
DELETE(*f->footnotes);
free(f->footnotes);
}
}
/* initialize a new MMIOT
*/
void
___mkd_initmmiot(MMIOT *f, void *footnotes)
{
if ( f ) {
memset(f, 0, sizeof *f);
CREATE(f->in);
CREATE(f->out);
CREATE(f->Q);
if ( footnotes )
f->footnotes = footnotes;
else {
f->footnotes = malloc(sizeof f->footnotes[0]);
CREATE(*f->footnotes);
}
}
}
/* free the contents of a MMIOT, but leave the object alone.
*/
void
___mkd_freemmiot(MMIOT *f, void *footnotes)
{
if ( f ) {
DELETE(f->in);
DELETE(f->out);
DELETE(f->Q);
if ( f->footnotes != footnotes )
___mkd_freefootnotes(f);
memset(f, 0, sizeof *f);
}
}
/* free lines up to an barrier.
*/
void
___mkd_freeLineRange(Line *anchor, Line *stop)
{
Line *r = anchor->next;
if ( r != stop ) {
while ( r && (r->next != stop) )
r = r->next;
if ( r ) r->next = 0;
___mkd_freeLines(anchor->next);
}
anchor->next = 0;
}
/* clean up everything allocated in __mkd_compile()
*/
void
mkd_cleanup(Document *doc)
{
if ( doc ) {
if ( doc->ctx ) {
___mkd_freemmiot(doc->ctx, 0);
free(doc->ctx);
}
if ( doc->code) ___mkd_freeParagraph(doc->code);
if ( doc->headers ) ___mkd_freeLines(doc->headers);
if ( T(doc->content) ) ___mkd_freeLines(T(doc->content));
memset(doc, 0, sizeof doc[0]);
free(doc);
}
}
/* write output in XML format
*/
void
___mkd_xml(char *p, int size, FILE *out)
{
char c;
while ( size-- > 0 ) {
if ( !isascii(c = *p++) )
continue;
switch (c) {
case '<': fputs("<", out); break;
case '>': fputs(">", out); break;
case '&': fputs("&", out); break;
case '"': fputs(""", out); break;
case '\'':fputs("'", out); break;
default: putc(c,out); break;
}
}
}
lua-discount-1.2.10.1/test_discount.lua 0000664 0000000 0000000 00000003140 11065704713 0017735 0 ustar 00root root 0000000 0000000 require("lunit")
discount = require("discount")
module("test discount", lunit.testcase, package.seeall)
function test_basic_conversion()
assert_equal("Hello World.
\n", discount("Hello World."))
end
function test_relaxed_emphasis()
assert_equal("Hello World !
\n", discount("_Hello World_!"))
assert_equal("under_score this_stuff
\n", discount("under_score this_stuff"))
local input = "_start _ foo_bar bar_baz _ end_ *italic* **bold** _blah_ "
local expected_out = "start _ foo_bar bar_baz _ end italic bold blah
\n"
assert_equal(expected_out, discount(input))
end
function test_nolinks()
assert_equal("[example](http://example.com)
\n", discount("[example](http://example.com)", "nolinks"))
assert_equal('<a href="http://example.com">example
\n',
discount('example ', "nolinks"))
end
function test_noimages()
assert_equal("
\n", discount("", "noimages"))
assert_equal('<img src="example.png"/>
\n', discount(' ', "noimages"))
end
function test_nopants()
assert_equal('“quote”
\n', discount('"quote"'))
assert_equal('"quote"
\n', discount('"quote"', "nopants"))
end
function test_nohtml()
local expected = "This should <em>not</em> be allowed
\n"
assert_equal(expected, discount("This should not be allowed", "nohtml"))
end
function test_cdata()
assert_equal("<p>foo</p>\n", discount("foo", "cdata"))
end