1 /* markdown: a C implementation of John Gruber's Markdown markup language.
2 *
3 * Copyright (C) 2007 David L Parsons.
4 * The redistribution terms are provided in the COPYRIGHT file that must
5 * be distributed with this source code.
6 */
7 #include <stdio.h>
8 #include "markdown.h"
9 #include "cstring.h"
10 #include "amalloc.h"
11
12 struct frame {
13 int indent;
14 char c;
15 };
16
17 typedef STRING(struct frame) Stack;
18
19 static char *
Pptype(int typ)20 Pptype(int typ)
21 {
22 switch (typ) {
23 case WHITESPACE: return "whitespace";
24 case CODE : return "code";
25 case QUOTE : return "quote";
26 case MARKUP : return "markup";
27 case HTML : return "html";
28 case DL : return "dl";
29 case UL : return "ul";
30 case OL : return "ol";
31 case LISTITEM : return "item";
32 case HDR : return "header";
33 case HR : return "hr";
34 case TABLE : return "table";
35 case SOURCE : return "source";
36 case STYLE : return "style";
37 default : return "mystery node!";
38 }
39 }
40
41 static void
pushpfx(int indent,char c,Stack * sp)42 pushpfx(int indent, char c, Stack *sp)
43 {
44 struct frame *q = &EXPAND(*sp);
45
46 q->indent = indent;
47 q->c = c;
48 }
49
50
51 static void
poppfx(Stack * sp)52 poppfx(Stack *sp)
53 {
54 S(*sp)--;
55 }
56
57
58 static void
changepfx(Stack * sp,char c)59 changepfx(Stack *sp, char c)
60 {
61 char ch;
62
63 if ( !S(*sp) ) return;
64
65 ch = T(*sp)[S(*sp)-1].c;
66
67 if ( ch == '+' || ch == '|' )
68 T(*sp)[S(*sp)-1].c = c;
69 }
70
71
72 static void
printpfx(Stack * sp,FILE * f)73 printpfx(Stack *sp, FILE *f)
74 {
75 int i;
76 char c;
77
78 if ( !S(*sp) ) return;
79
80 c = T(*sp)[S(*sp)-1].c;
81
82 if ( c == '+' || c == '-' ) {
83 fprintf(f, "--%c", c);
84 T(*sp)[S(*sp)-1].c = (c == '-') ? ' ' : '|';
85 }
86 else
87 for ( i=0; i < S(*sp); i++ ) {
88 if ( i )
89 fprintf(f, " ");
90 fprintf(f, "%*s%c", T(*sp)[i].indent + 2, " ", T(*sp)[i].c);
91 if ( T(*sp)[i].c == '`' )
92 T(*sp)[i].c = ' ';
93 }
94 fprintf(f, "--");
95 }
96
97
98 static void
dumptree(Paragraph * pp,Stack * sp,FILE * f)99 dumptree(Paragraph *pp, Stack *sp, FILE *f)
100 {
101 int count;
102 Line *p;
103 int d;
104 static char *Begin[] = { 0, "P", "center" };
105
106 while ( pp ) {
107 if ( !pp->next )
108 changepfx(sp, '`');
109 printpfx(sp, f);
110
111 if ( pp->typ == HDR )
112 d += fprintf(f, "[h%d", pp->hnumber);
113 else
114 d = fprintf(f, "[%s", Pptype(pp->typ));
115 if ( pp->ident )
116 d += fprintf(f, " %s", pp->ident);
117
118 #ifdef GITHUB_CHECKBOX
119 if ( pp->flags )
120 d += fprintf(f, " %x", pp->flags);
121 #endif
122
123 if ( pp->align > 1 )
124 d += fprintf(f, ", <%s>", Begin[pp->align]);
125
126 for (count=0, p=pp->text; p; ++count, (p = p->next) )
127 ;
128
129 if ( count )
130 d += fprintf(f, ", %d line%s", count, (count==1)?"":"s");
131
132 d += fprintf(f, "]");
133
134 if ( pp->down ) {
135 pushpfx(d, pp->down->next ? '+' : '-', sp);
136 dumptree(pp->down, sp, f);
137 poppfx(sp);
138 }
139 else fputc('\n', f);
140 pp = pp->next;
141 }
142 }
143
144
145 int
mkd_dump(Document * doc,FILE * out,mkd_flag_t flags,char * title)146 mkd_dump(Document *doc, FILE *out, mkd_flag_t flags, char *title)
147 {
148 Stack stack;
149
150 if (mkd_compile(doc, flags) ) {
151
152 CREATE(stack);
153 pushpfx(fprintf(out, "%s", title), doc->code->next ? '+' : '-', &stack);
154 dumptree(doc->code, &stack, out);
155 DELETE(stack);
156
157 return 0;
158 }
159 return -1;
160 }
161