1 #line 100 "../mdcode.mdc"
8 #line 461 "../mdcode.mdc"
12 #line 179 "../mdcode.mdc"
15 struct code_node *last;
20 #line 216 "../mdcode.mdc"
21 static void code_linearize(struct code_node *code)
24 for (t = code; t; t = t->next)
26 for (; code; code = code->next)
28 struct code_node *next = code->next;
29 struct psection *pchild =
30 (struct psection *)code->child;
31 int indent = pchild->indent;
32 code->next = code->child->code;
33 code->child->code = NULL;
35 for (t = code; t->next; t = t->next)
36 t->next->indent = code->indent + indent;
41 #line 239 "../mdcode.mdc"
42 void code_free(struct code_node *code)
45 struct code_node *this;
54 #line 268 "../mdcode.mdc"
55 static void code_add_text(struct psection *where, struct text txt,
61 n = malloc(sizeof(*n));
68 where->last->next = n;
74 #line 290 "../mdcode.mdc"
75 void code_add_link(struct psection *where, struct psection *to,
81 to->refcnt++; // this will be checked elsewhere
82 if (where->last && where->last->child == NULL) {
83 where->last->child = to;
86 n = malloc(sizeof(*n));
93 where->last->next = n;
99 #line 329 "../mdcode.mdc"
100 static int text_cmp(struct text a, struct text b)
103 return a.len - b.len;
104 return strncmp(a.txt, b.txt, a.len);
107 static struct psection *section_find(struct psection **list, struct text name)
109 struct psection *new;
111 int cmp = text_cmp((*list)->section, name);
116 list = (struct psection **)&((*list)->next);
118 /* Add this section */
119 new = malloc(sizeof(*new));
130 #line 410 "../mdcode.mdc"
131 static char *skip_lws(char *pos, char *end)
133 while (pos < end && (*pos == ' ' || *pos == '\t'))
138 static char *skip_line(char *pos, char *end)
140 while (pos < end && *pos != '\n')
147 static char *skip_para(char *pos, char *end, int *line_no)
149 /* Might return a pointer to a blank line, as only
150 * one trailing blank line is skipped
153 pos = skip_line(pos, end);
159 *(pos = skip_lws(pos, end)) != '\n') {
160 pos = skip_line(pos, end);
163 if (pos < end && *pos == '\n') {
170 #line 466 "../mdcode.mdc"
171 static struct text take_header(char *pos, char *end)
175 while (pos < end && *pos == '#')
177 while (pos < end && *pos == ' ')
180 while (pos < end && *pos != '\n')
182 while (pos > section.txt &&
183 (pos[-1] == '#' || pos[-1] == ' '))
185 section.len = pos - section.txt;
189 static int is_list(char *pos, char *end)
191 if (strchr("-*+", *pos))
194 while (pos < end && isdigit(*pos))
196 if (pos < end && *pos == '.')
202 static int matches(char *start, char *pos, char *end)
205 return matches("\t", pos, end) ||
206 matches(" ", pos, end);
207 return (pos + strlen(start) < end &&
208 strncmp(pos, start, strlen(start)) == 0);
211 #line 538 "../mdcode.mdc"
212 static int count_space(char *sol, char *p)
226 static char *take_code(char *pos, char *end, char *marker,
227 struct psection **table, struct text section,
231 int line_no = *line_nop;
232 int start_line = line_no;
233 struct psection *sect;
235 sect = section_find(table, section);
241 if (marker && matches(marker, pos, end))
244 (skip_lws(pos, end))[0] != '\n' &&
245 !matches(NULL, pos, end))
246 /* Paragraph not indented */
249 /* Still in code - check for reference */
254 else if (strcmp(sol, " ") == 0)
257 t = skip_lws(sol, end);
258 if (t[0] != '#' || t[1] != '#') {
259 /* Just regular code here */
260 pos = skip_line(sol, end);
268 txt.len = pos - start;
269 code_add_text(sect, txt, start_line);
271 ref = take_header(t, end);
273 struct psection *refsec = section_find(table, ref);
274 code_add_link(sect, refsec, count_space(sol, t));
276 pos = skip_line(t, end);
279 start_line = line_no;
284 txt.len = pos - start;
285 code_add_text(sect, txt, start_line);
288 pos = skip_line(pos, end);
295 #line 630 "../mdcode.mdc"
296 static struct psection *code_find(char *pos, char *end)
298 struct psection *table = NULL;
301 struct text section = {0};
305 section = take_header(pos, end);
307 pos = skip_line(pos, end);
309 } else if (is_list(pos, end)) {
311 pos = skip_para(pos, end, &line_no);
312 } else if (!in_list && matches(NULL, pos, end)) {
313 pos = take_code(pos, end, NULL, &table,
315 } else if (matches("```", pos, end)) {
317 pos = skip_line(pos, end);
319 pos = take_code(pos, end, "```", &table,
321 } else if (matches("~~~", pos, end)) {
323 pos = skip_line(pos, end);
325 pos = take_code(pos, end, "~~~", &table,
330 pos = skip_para(pos, end, &line_no);
336 #line 690 "../mdcode.mdc"
337 struct section *code_extract(char *pos, char *end, code_err_fn error)
339 struct psection *table;
340 struct section *result = NULL;
341 struct section *tofree = NULL;
343 table = code_find(pos, end);
346 struct psection *t = (struct psection*)table->next;
347 if (table->last == NULL) {
350 "Section \"%.*s\" is referenced but not declared",
351 table->section.len, table->section.txt);
355 if (table->refcnt == 0) {
356 /* Root-section, return it */
357 table->next = result;
359 code_linearize(result->code);
361 table->next = tofree;
363 if (table->refcnt > 1) {
366 "Section \"%.*s\" referenced multiple times (%d).",
367 table->section.len, table->section.txt,
376 struct section *t = tofree->next;
383 #line 109 "../mdcode.mdc"