1 #line 101 "../mdcode.mdc"
8 #line 470 "../mdcode.mdc"
12 #line 187 "../mdcode.mdc"
15 struct code_node *last;
20 #line 224 "../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 247 "../mdcode.mdc"
42 void code_free(struct code_node *code)
45 struct code_node *this;
54 #line 276 "../mdcode.mdc"
55 static void code_add_text(struct psection *where, struct text txt,
56 int line_no, int needs_strip)
61 n = malloc(sizeof(*n));
65 n->needs_strip = needs_strip;
69 where->last->next = n;
75 #line 299 "../mdcode.mdc"
76 void code_add_link(struct psection *where, struct psection *to,
82 to->refcnt++; // this will be checked elsewhere
83 if (where->last && where->last->child == NULL) {
84 where->last->child = to;
87 n = malloc(sizeof(*n));
94 where->last->next = n;
100 #line 338 "../mdcode.mdc"
101 static int text_cmp(struct text a, struct text b)
104 return a.len - b.len;
105 return strncmp(a.txt, b.txt, a.len);
108 static struct psection *section_find(struct psection **list, struct text name)
110 struct psection *new;
112 int cmp = text_cmp((*list)->section, name);
117 list = (struct psection **)&((*list)->next);
119 /* Add this section */
120 new = malloc(sizeof(*new));
131 #line 419 "../mdcode.mdc"
132 static char *skip_lws(char *pos, char *end)
134 while (pos < end && (*pos == ' ' || *pos == '\t'))
139 static char *skip_line(char *pos, char *end)
141 while (pos < end && *pos != '\n')
148 static char *skip_para(char *pos, char *end, int *line_no)
150 /* Might return a pointer to a blank line, as only
151 * one trailing blank line is skipped
154 pos = skip_line(pos, end);
160 *(pos = skip_lws(pos, end)) != '\n') {
161 pos = skip_line(pos, end);
164 if (pos < end && *pos == '\n') {
171 #line 475 "../mdcode.mdc"
172 static struct text take_header(char *pos, char *end)
176 while (pos < end && *pos == '#')
178 while (pos < end && *pos == ' ')
181 while (pos < end && *pos != '\n')
183 while (pos > section.txt &&
184 (pos[-1] == '#' || pos[-1] == ' '))
186 section.len = pos - section.txt;
190 static int is_list(char *pos, char *end)
192 if (strchr("-*+", *pos))
195 while (pos < end && isdigit(*pos))
197 if (pos < end && *pos == '.')
203 static int matches(char *start, char *pos, char *end)
206 return matches("\t", pos, end) ||
207 matches(" ", pos, end);
208 return (pos + strlen(start) < end &&
209 strncmp(pos, start, strlen(start)) == 0);
212 #line 547 "../mdcode.mdc"
213 static int count_space(char *sol, char *p)
227 static char *take_code(char *pos, char *end, char *marker,
228 struct psection **table, struct text section,
232 int line_no = *line_nop;
233 int start_line = line_no;
234 struct psection *sect;
236 sect = section_find(table, section);
242 if (marker && matches(marker, pos, end))
245 (skip_lws(pos, end))[0] != '\n' &&
246 !matches(NULL, pos, end))
247 /* Paragraph not indented */
250 /* Still in code - check for reference */
255 else if (strcmp(sol, " ") == 0)
258 t = skip_lws(sol, end);
259 if (t[0] != '#' || t[1] != '#') {
260 /* Just regular code here */
261 pos = skip_line(sol, end);
269 txt.len = pos - start;
270 code_add_text(sect, txt, start_line,
273 ref = take_header(t, end);
275 struct psection *refsec = section_find(table, ref);
276 code_add_link(sect, refsec, count_space(sol, t));
278 pos = skip_line(t, end);
281 start_line = line_no;
286 txt.len = pos - start;
287 code_add_text(sect, txt, start_line,
291 pos = skip_line(pos, end);
298 #line 641 "../mdcode.mdc"
299 static struct psection *code_find(char *pos, char *end)
301 struct psection *table = NULL;
304 struct text section = {0};
308 section = take_header(pos, end);
310 pos = skip_line(pos, end);
312 } else if (is_list(pos, end)) {
314 pos = skip_para(pos, end, &line_no);
315 } else if (!in_list && matches(NULL, pos, end)) {
316 pos = take_code(pos, end, NULL, &table,
318 } else if (matches("```", pos, end)) {
320 pos = skip_line(pos, end);
322 pos = take_code(pos, end, "```", &table,
324 } else if (matches("~~~", pos, end)) {
326 pos = skip_line(pos, end);
328 pos = take_code(pos, end, "~~~", &table,
333 pos = skip_para(pos, end, &line_no);
339 #line 701 "../mdcode.mdc"
340 struct section *code_extract(char *pos, char *end, code_err_fn error)
342 struct psection *table;
343 struct section *result = NULL;
344 struct section *tofree = NULL;
346 table = code_find(pos, end);
349 struct psection *t = (struct psection*)table->next;
350 if (table->last == NULL) {
353 "Section \"%.*s\" is referenced but not declared",
354 table->section.len, table->section.txt);
358 if (table->refcnt == 0) {
359 /* Root-section, return it */
360 table->next = result;
362 code_linearize(result->code);
364 table->next = tofree;
366 if (table->refcnt > 1) {
369 "Section \"%.*s\" referenced multiple times (%d).",
370 table->section.len, table->section.txt,
379 struct section *t = tofree->next;
386 #line 782 "../mdcode.mdc"
387 void code_node_print(FILE *out, struct code_node *node,
390 for (; node; node = node->next) {
391 char *c = node->code.txt;
392 int len = node->code.len;
397 fprintf(out, "#line %d \"%s\"\n",
398 node->line_no, fname);
400 fprintf(out, "%*s", node->indent, "");
401 if (node->needs_strip) {
402 if (*c == '\t' && len > 1) {
405 } else if (strncmp(c, " ", 4) == 0 && len > 4) {
414 } while (len && c[-1] != '\n');
419 #line 110 "../mdcode.mdc"