rdiscount-dsc 1.6.9

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,169 @@
1
+ #ifndef _MARKDOWN_D
2
+ #define _MARKDOWN_D
3
+
4
+ #include "cstring.h"
5
+
6
+ /* reference-style links (and images) are stored in an array
7
+ * of footnotes.
8
+ */
9
+ typedef struct footnote {
10
+ Cstring tag; /* the tag for the reference link */
11
+ Cstring link; /* what this footnote points to */
12
+ Cstring title; /* what it's called (TITLE= attribute) */
13
+ int height, width; /* dimensions (for image link) */
14
+ int dealloc; /* deallocation needed? */
15
+ } Footnote;
16
+
17
+ /* each input line is read into a Line, which contains the line,
18
+ * the offset of the first non-space character [this assumes
19
+ * that all tabs will be expanded to spaces!], and a pointer to
20
+ * the next line.
21
+ */
22
+ typedef struct line {
23
+ Cstring text;
24
+ struct line *next;
25
+ int dle;
26
+ } Line;
27
+
28
+
29
+ /* a paragraph is a collection of Lines, with links to the next paragraph
30
+ * and (if it's a QUOTE, UL, or OL) to the reparsed contents of this
31
+ * paragraph.
32
+ */
33
+ typedef struct paragraph {
34
+ struct paragraph *next; /* next paragraph */
35
+ struct paragraph *down; /* recompiled contents of this paragraph */
36
+ struct line *text; /* all the text in this paragraph */
37
+ char *ident; /* %id% tag for QUOTE */
38
+ enum { WHITESPACE=0, CODE, QUOTE, MARKUP,
39
+ HTML, STYLE, DL, UL, OL, AL, LISTITEM,
40
+ HDR, HR, TABLE, SOURCE } typ;
41
+ enum { IMPLICIT=0, PARA, CENTER} align;
42
+ int hnumber; /* <Hn> for typ == HDR */
43
+ } Paragraph;
44
+
45
+ enum { ETX, SETEXT }; /* header types */
46
+
47
+
48
+ typedef struct block {
49
+ enum { bTEXT, bSTAR, bUNDER } b_type;
50
+ int b_count;
51
+ char b_char;
52
+ Cstring b_text;
53
+ Cstring b_post;
54
+ } block;
55
+
56
+ typedef STRING(block) Qblock;
57
+
58
+
59
+ typedef char* (*mkd_callback_t)(const char*, const int, void*);
60
+ typedef void (*mkd_free_t)(char*, void*);
61
+
62
+ typedef struct callback_data {
63
+ void *e_data; /* private data for callbacks */
64
+ mkd_callback_t e_url; /* url edit callback */
65
+ mkd_callback_t e_flags; /* extra href flags callback */
66
+ mkd_free_t e_free; /* edit/flags callback memory deallocator */
67
+ } Callback_data;
68
+
69
+
70
+ /* a magic markdown io thing holds all the data structures needed to
71
+ * do the backend processing of a markdown document
72
+ */
73
+ typedef struct mmiot {
74
+ Cstring out;
75
+ Cstring in;
76
+ Qblock Q;
77
+ int isp;
78
+ STRING(Footnote) *footnotes;
79
+ DWORD flags;
80
+ #define MKD_NOLINKS 0x00000001
81
+ #define MKD_NOIMAGE 0x00000002
82
+ #define MKD_NOPANTS 0x00000004
83
+ #define MKD_NOHTML 0x00000008
84
+ #define MKD_STRICT 0x00000010
85
+ #define MKD_TAGTEXT 0x00000020
86
+ #define MKD_NO_EXT 0x00000040
87
+ #define MKD_CDATA 0x00000080
88
+ #define MKD_NOSUPERSCRIPT 0x00000100
89
+ #define MKD_NORELAXED 0x00000200
90
+ #define MKD_NOTABLES 0x00000400
91
+ #define MKD_NOSTRIKETHROUGH 0x00000800
92
+ #define MKD_TOC 0x00001000
93
+ #define MKD_1_COMPAT 0x00002000
94
+ #define MKD_AUTOLINK 0x00004000
95
+ #define MKD_SAFELINK 0x00008000
96
+ #define MKD_NOHEADER 0x00010000
97
+ #define MKD_TABSTOP 0x00020000
98
+ #define MKD_NODIVQUOTE 0x00040000
99
+ #define MKD_NOALPHALIST 0x00080000
100
+ #define MKD_NODLIST 0x00100000
101
+ #define IS_LABEL 0x08000000
102
+ #define USER_FLAGS 0x0FFFFFFF
103
+ #define INPUT_MASK (MKD_NOHEADER|MKD_TABSTOP)
104
+
105
+ Callback_data *cb;
106
+ } MMIOT;
107
+
108
+
109
+ /*
110
+ * the mkdio text input functions return a document structure,
111
+ * which contains a header (retrieved from the document if
112
+ * markdown was configured * with the * --enable-pandoc-header
113
+ * and the document begins with a pandoc-style header) and the
114
+ * root of the linked list of Lines.
115
+ */
116
+ typedef struct document {
117
+ int magic; /* "I AM VALID" magic number */
118
+ #define VALID_DOCUMENT 0x19600731
119
+ Line *title;
120
+ Line *author;
121
+ Line *date;
122
+ ANCHOR(Line) content; /* uncompiled text, not valid after compile() */
123
+ Paragraph *code; /* intermediate code generated by compile() */
124
+ int compiled; /* set after mkd_compile() */
125
+ int html; /* set after (internal) htmlify() */
126
+ int tabstop; /* for properly expanding tabs (ick) */
127
+ MMIOT *ctx; /* backend buffers, flags, and structures */
128
+ Callback_data cb; /* callback functions & private data */
129
+ } Document;
130
+
131
+
132
+ extern int mkd_firstnonblank(Line *);
133
+ extern int mkd_compile(Document *, DWORD);
134
+ extern int mkd_document(Document *, char **);
135
+ extern int mkd_generatehtml(Document *, FILE *);
136
+ extern int mkd_css(Document *, char **);
137
+ extern int mkd_generatecss(Document *, FILE *);
138
+ #define mkd_style mkd_generatecss
139
+ extern int mkd_xml(char *, int , char **);
140
+ extern int mkd_generatexml(char *, int, FILE *);
141
+ extern void mkd_cleanup(Document *);
142
+ extern int mkd_line(char *, int, char **, DWORD);
143
+ extern int mkd_generateline(char *, int, FILE*, DWORD);
144
+ #define mkd_text mkd_generateline
145
+ extern void mkd_basename(Document*, char *);
146
+ extern void mkd_string_to_anchor(char*,int, void(*)(int,void*), void*, int);
147
+
148
+ extern Document *mkd_in(FILE *, DWORD);
149
+ extern Document *mkd_string(char*,int, DWORD);
150
+
151
+ extern void mkd_initialize();
152
+ extern void mkd_shlib_destructor();
153
+
154
+ /* internal resource handling functions.
155
+ */
156
+ extern void ___mkd_freeLine(Line *);
157
+ extern void ___mkd_freeLines(Line *);
158
+ extern void ___mkd_freeParagraph(Paragraph *);
159
+ extern void ___mkd_freefootnote(Footnote *);
160
+ extern void ___mkd_freefootnotes(MMIOT *);
161
+ extern void ___mkd_initmmiot(MMIOT *, void *);
162
+ extern void ___mkd_freemmiot(MMIOT *, void *);
163
+ extern void ___mkd_freeLineRange(Line *, Line *);
164
+ extern void ___mkd_xml(char *, int, FILE *);
165
+ extern void ___mkd_reparse(char *, int, int, MMIOT*);
166
+ extern void ___mkd_emblock(MMIOT*);
167
+ extern void ___mkd_tidy(Cstring *);
168
+
169
+ #endif/*_MARKDOWN_D*/
@@ -0,0 +1,344 @@
1
+ /*
2
+ * mkdio -- markdown front end input functions
3
+ *
4
+ * Copyright (C) 2007 David L Parsons.
5
+ * The redistribution terms are provided in the COPYRIGHT file that must
6
+ * be distributed with this source code.
7
+ */
8
+ #include "config.h"
9
+ #include <stdio.h>
10
+ #include <stdlib.h>
11
+ #include <ctype.h>
12
+
13
+ #include "cstring.h"
14
+ #include "markdown.h"
15
+ #include "amalloc.h"
16
+
17
+ typedef ANCHOR(Line) LineAnchor;
18
+
19
+ /* create a new blank Document
20
+ */
21
+ static Document*
22
+ new_Document()
23
+ {
24
+ Document *ret = calloc(sizeof(Document), 1);
25
+
26
+ if ( ret ) {
27
+ if (( ret->ctx = calloc(sizeof(MMIOT), 1) )) {
28
+ ret->magic = VALID_DOCUMENT;
29
+ return ret;
30
+ }
31
+ free(ret);
32
+ }
33
+ return 0;
34
+ }
35
+
36
+
37
+ /* add a line to the markdown input chain
38
+ */
39
+ static void
40
+ queue(Document* a, Cstring *line)
41
+ {
42
+ Line *p = calloc(sizeof *p, 1);
43
+ unsigned char c;
44
+ int xp = 0;
45
+ int size = S(*line);
46
+ unsigned char *str = (unsigned char*)T(*line);
47
+
48
+ CREATE(p->text);
49
+ ATTACH(a->content, p);
50
+
51
+ while ( size-- ) {
52
+ if ( (c = *str++) == '\t' ) {
53
+ /* expand tabs into ->tabstop spaces. We use ->tabstop
54
+ * because the ENTIRE FREAKING COMPUTER WORLD uses editors
55
+ * that don't do ^T/^D, but instead use tabs for indentation,
56
+ * and, of course, set their tabs down to 4 spaces
57
+ */
58
+ do {
59
+ EXPAND(p->text) = ' ';
60
+ } while ( ++xp % a->tabstop );
61
+ }
62
+ else if ( c >= ' ' ) {
63
+ EXPAND(p->text) = c;
64
+ ++xp;
65
+ }
66
+ }
67
+ EXPAND(p->text) = 0;
68
+ S(p->text)--;
69
+ p->dle = mkd_firstnonblank(p);
70
+ }
71
+
72
+
73
+ /* trim leading blanks from a header line
74
+ */
75
+ static void
76
+ header_dle(Line *p)
77
+ {
78
+ CLIP(p->text, 0, 1);
79
+ p->dle = mkd_firstnonblank(p);
80
+ }
81
+
82
+
83
+ /* build a Document from any old input.
84
+ */
85
+ typedef int (*getc_func)(void*);
86
+
87
+ Document *
88
+ populate(getc_func getc, void* ctx, int flags)
89
+ {
90
+ Cstring line;
91
+ Document *a = new_Document();
92
+ int c;
93
+ int pandoc = 0;
94
+
95
+ if ( !a ) return 0;
96
+
97
+ a->tabstop = (flags & MKD_TABSTOP) ? 4 : TABSTOP;
98
+
99
+ CREATE(line);
100
+
101
+ while ( (c = (*getc)(ctx)) != EOF ) {
102
+ if ( c == '\n' ) {
103
+ if ( pandoc != EOF && pandoc < 3 ) {
104
+ if ( S(line) && (T(line)[0] == '%') )
105
+ pandoc++;
106
+ else
107
+ pandoc = EOF;
108
+ }
109
+ queue(a, &line);
110
+ S(line) = 0;
111
+ }
112
+ else if ( isprint(c) || isspace(c) || (c & 0x80) )
113
+ EXPAND(line) = c;
114
+ }
115
+
116
+ if ( S(line) )
117
+ queue(a, &line);
118
+
119
+ DELETE(line);
120
+
121
+ if ( (pandoc == 3) && !(flags & (MKD_NOHEADER|MKD_STRICT)) ) {
122
+ /* the first three lines started with %, so we have a header.
123
+ * clip the first three lines out of content and hang them
124
+ * off header.
125
+ */
126
+ Line *headers = T(a->content);
127
+
128
+ a->title = headers; header_dle(a->title);
129
+ a->author= headers->next; header_dle(a->author);
130
+ a->date = headers->next->next; header_dle(a->date);
131
+
132
+ T(a->content) = headers->next->next->next;
133
+ }
134
+
135
+ return a;
136
+ }
137
+
138
+
139
+ /* convert a file into a linked list
140
+ */
141
+ Document *
142
+ mkd_in(FILE *f, DWORD flags)
143
+ {
144
+ return populate((getc_func)fgetc, f, flags & INPUT_MASK);
145
+ }
146
+
147
+
148
+ /* return a single character out of a buffer
149
+ */
150
+ struct string_ctx {
151
+ char *data; /* the unread data */
152
+ int size; /* and how much is there? */
153
+ } ;
154
+
155
+
156
+ static int
157
+ strget(struct string_ctx *in)
158
+ {
159
+ if ( !in->size ) return EOF;
160
+
161
+ --(in->size);
162
+
163
+ return *(in->data)++;
164
+ }
165
+
166
+
167
+ /* convert a block of text into a linked list
168
+ */
169
+ Document *
170
+ mkd_string(char *buf, int len, DWORD flags)
171
+ {
172
+ struct string_ctx about;
173
+
174
+ about.data = buf;
175
+ about.size = len;
176
+
177
+ return populate((getc_func)strget, &about, flags & INPUT_MASK);
178
+ }
179
+
180
+
181
+ /* write the html to a file (xmlified if necessary)
182
+ */
183
+ int
184
+ mkd_generatehtml(Document *p, FILE *output)
185
+ {
186
+ char *doc;
187
+ int szdoc;
188
+
189
+ if ( (szdoc = mkd_document(p, &doc)) != EOF ) {
190
+ if ( p->ctx->flags & MKD_CDATA )
191
+ mkd_generatexml(doc, szdoc, output);
192
+ else
193
+ fwrite(doc, szdoc, 1, output);
194
+ putc('\n', output);
195
+ return 0;
196
+ }
197
+ return -1;
198
+ }
199
+
200
+
201
+ /* convert some markdown text to html
202
+ */
203
+ int
204
+ markdown(Document *document, FILE *out, int flags)
205
+ {
206
+ if ( mkd_compile(document, flags) ) {
207
+ mkd_generatehtml(document, out);
208
+ mkd_cleanup(document);
209
+ return 0;
210
+ }
211
+ return -1;
212
+ }
213
+
214
+
215
+ /* write out a Cstring, mangled into a form suitable for `<a href=` or `<a id=`
216
+ */
217
+ void
218
+ mkd_string_to_anchor(char *s, int len, void(*outchar)(int,void*),
219
+ void *out, int labelformat)
220
+ {
221
+ unsigned char c;
222
+
223
+ int i, size;
224
+ char *line;
225
+
226
+ size = mkd_line(s, len, &line, IS_LABEL);
227
+
228
+ if ( labelformat && size && !isalpha(line[0]) )
229
+ (*outchar)('L',out);
230
+ for ( i=0; i < size ; i++ ) {
231
+ c = line[i];
232
+ if ( labelformat ) {
233
+ if ( isalnum(c) || (c == '_') || (c == ':') || (c == '-') || (c == '.' ) )
234
+ (*outchar)(c, out);
235
+ else
236
+ (*outchar)('.',out);
237
+ }
238
+ else
239
+ (*outchar)(c,out);
240
+ }
241
+
242
+ if (line)
243
+ free(line);
244
+ }
245
+
246
+
247
+ /* ___mkd_reparse() a line
248
+ */
249
+ static void
250
+ mkd_parse_line(char *bfr, int size, MMIOT *f, int flags)
251
+ {
252
+ ___mkd_initmmiot(f, 0);
253
+ f->flags = flags & USER_FLAGS;
254
+ ___mkd_reparse(bfr, size, 0, f);
255
+ ___mkd_emblock(f);
256
+ }
257
+
258
+
259
+ /* ___mkd_reparse() a line, returning it in malloc()ed memory
260
+ */
261
+ int
262
+ mkd_line(char *bfr, int size, char **res, DWORD flags)
263
+ {
264
+ MMIOT f;
265
+ int len;
266
+
267
+ mkd_parse_line(bfr, size, &f, flags);
268
+
269
+ if ( len = S(f.out) ) {
270
+ /* kludge alert; we know that T(f.out) is malloced memory,
271
+ * so we can just steal it away. This is awful -- there
272
+ * should be an opaque method that transparently moves
273
+ * the pointer out of the embedded Cstring.
274
+ */
275
+ EXPAND(f.out) = 0;
276
+ *res = T(f.out);
277
+ T(f.out) = 0;
278
+ S(f.out) = ALLOCATED(f.out) = 0;
279
+ }
280
+ else {
281
+ *res = 0;
282
+ len = EOF;
283
+ }
284
+ ___mkd_freemmiot(&f, 0);
285
+ return len;
286
+ }
287
+
288
+
289
+ /* ___mkd_reparse() a line, writing it to a FILE
290
+ */
291
+ int
292
+ mkd_generateline(char *bfr, int size, FILE *output, DWORD flags)
293
+ {
294
+ MMIOT f;
295
+
296
+ mkd_parse_line(bfr, size, &f, flags);
297
+ if ( flags & MKD_CDATA )
298
+ mkd_generatexml(T(f.out), S(f.out), output);
299
+ else
300
+ fwrite(T(f.out), S(f.out), 1, output);
301
+
302
+ ___mkd_freemmiot(&f, 0);
303
+ return 0;
304
+ }
305
+
306
+
307
+ /* set the url display callback
308
+ */
309
+ void
310
+ mkd_e_url(Document *f, mkd_callback_t edit)
311
+ {
312
+ if ( f )
313
+ f->cb.e_url = edit;
314
+ }
315
+
316
+
317
+ /* set the url options callback
318
+ */
319
+ void
320
+ mkd_e_flags(Document *f, mkd_callback_t edit)
321
+ {
322
+ if ( f )
323
+ f->cb.e_flags = edit;
324
+ }
325
+
326
+
327
+ /* set the url display/options deallocator
328
+ */
329
+ void
330
+ mkd_e_free(Document *f, mkd_free_t dealloc)
331
+ {
332
+ if ( f )
333
+ f->cb.e_free = dealloc;
334
+ }
335
+
336
+
337
+ /* set the url display/options context data field
338
+ */
339
+ void
340
+ mkd_e_data(Document *f, void *data)
341
+ {
342
+ if ( f )
343
+ f->cb.e_data = data;
344
+ }