1 #line 106 "../mdcode.mdc"
8 #line 493 "../mdcode.mdc"
11 #line 194 "../mdcode.mdc"
14 struct code_node *last;
18 #line 231 "../mdcode.mdc"
19 static void code_linearize(struct code_node *code)
22 for (t = code; t; t = t->next)
24 for (; code; code = code->next)
26 struct code_node *next = code->next;
27 struct psection *pchild =
28 (struct psection *)code->child;
29 int indent = pchild->indent;
30 code->next = code->child->code;
31 code->child->code = NULL;
33 for (t = code; t->next; t = t->next)
34 t->next->indent = code->indent + indent;
38 #line 254 "../mdcode.mdc"
39 void code_free(struct code_node *code)
42 struct code_node *this;
50 #line 283 "../mdcode.mdc"
51 static void code_add_text(struct psection *where, struct text txt,
52 int line_no, int needs_strip)
57 n = malloc(sizeof(*n));
62 if (txt.txt[0] == '\t')
71 where->last->next = n;
76 #line 312 "../mdcode.mdc"
77 void code_add_link(struct psection *where, struct psection *to,
83 to->refcnt++; // this will be checked elsewhere
84 if (where->last && where->last->child == NULL) {
85 where->last->child = to;
88 n = malloc(sizeof(*n));
95 where->last->next = n;
100 #line 356 "../mdcode.mdc"
101 int text_cmp(struct text a, struct text b)
106 int cmp = strncmp(a.txt, b.txt, len);
110 return a.len - b.len;
113 static struct psection *section_find(struct psection **list, struct text name)
115 struct psection *new;
117 int cmp = text_cmp((*list)->section, name);
122 list = (struct psection **)&((*list)->next);
124 /* Add this section */
125 new = malloc(sizeof(*new));
135 #line 442 "../mdcode.mdc"
136 static char *skip_lws(char *pos, char *end)
138 while (pos < end && (*pos == ' ' || *pos == '\t'))
143 static char *skip_line(char *pos, char *end)
145 while (pos < end && *pos != '\n')
152 static char *skip_para(char *pos, char *end, int *line_no)
154 /* Might return a pointer to a blank line, as only
155 * one trailing blank line is skipped
158 pos = skip_line(pos, end);
164 *(pos = skip_lws(pos, end)) != '\n') {
165 pos = skip_line(pos, end);
168 if (pos < end && *pos == '\n') {
174 #line 498 "../mdcode.mdc"
175 static struct text take_header(char *pos, char *end)
179 while (pos < end && *pos == '#')
181 while (pos < end && *pos == ' ')
184 while (pos < end && *pos != '\n')
186 while (pos > section.txt &&
187 (pos[-1] == '#' || pos[-1] == ' '))
189 section.len = pos - section.txt;
193 static int is_list(char *pos, char *end)
195 if (strchr("-*+", *pos))
198 while (pos < end && isdigit(*pos))
200 if (pos < end && *pos == '.')
206 static int matches(char *start, char *pos, char *end)
209 return matches("\t", pos, end) ||
210 matches(" ", pos, end);
211 return (pos + strlen(start) < end &&
212 strncmp(pos, start, strlen(start)) == 0);
214 #line 575 "../mdcode.mdc"
215 static int count_space(char *sol, char *p)
228 static char *take_code(char *pos, char *end, char *marker,
229 struct psection **table, struct text section,
233 int line_no = *line_nop;
234 int start_line = line_no;
235 struct psection *sect;
237 sect = section_find(table, section);
243 if (marker && matches(marker, pos, end))
246 (skip_lws(pos, end))[0] != '\n' &&
247 !matches(NULL, pos, end))
248 /* Paragraph not indented */
251 /* Still in code - check for reference */
256 else if (strcmp(sol, " ") == 0)
259 t = skip_lws(sol, end);
260 if (t[0] != '#' || t[1] != '#') {
261 /* Just regular code here */
262 pos = skip_line(sol, end);
270 txt.len = pos - start;
271 code_add_text(sect, txt, start_line,
274 ref = take_header(t, end);
276 struct psection *refsec = section_find(table, ref);
277 code_add_link(sect, refsec, count_space(sol, t));
279 pos = skip_line(t, end);
282 start_line = line_no;
287 txt.len = pos - start;
288 /* strip trailing blank lines */
289 while (!marker && txt.len > 2 &&
290 start[txt.len-1] == '\n' &&
291 start[txt.len-2] == '\n')
294 code_add_text(sect, txt, start_line,
298 pos = skip_line(pos, end);
304 #line 674 "../mdcode.mdc"
305 static struct psection *code_find(char *pos, char *end)
307 struct psection *table = NULL;
310 struct text section = {0};
314 section = take_header(pos, end);
316 pos = skip_line(pos, end);
318 } else if (is_list(pos, end)) {
320 pos = skip_para(pos, end, &line_no);
321 } else if (!in_list && matches(NULL, pos, end)) {
322 pos = take_code(pos, end, NULL, &table,
324 } else if (matches("```", pos, end)) {
326 pos = skip_line(pos, end);
328 pos = take_code(pos, end, "```", &table,
330 } else if (matches("~~~", pos, end)) {
332 pos = skip_line(pos, end);
334 pos = take_code(pos, end, "~~~", &table,
339 pos = skip_para(pos, end, &line_no);
344 #line 734 "../mdcode.mdc"
345 struct section *code_extract(char *pos, char *end, code_err_fn error)
347 struct psection *table;
348 struct section *result = NULL;
349 struct section *tofree = NULL;
351 table = code_find(pos, end);
354 struct psection *t = (struct psection*)table->next;
355 if (table->last == NULL) {
358 "Section \"%.*s\" is referenced but not declared",
359 table->section.len, table->section.txt);
363 if (table->refcnt == 0) {
364 /* Root-section, return it */
365 table->next = result;
367 code_linearize(result->code);
369 table->next = tofree;
371 if (table->refcnt > 1) {
374 "Section \"%.*s\" referenced multiple times (%d).",
375 table->section.len, table->section.txt,
384 struct section *t = tofree->next;
390 #line 814 "../mdcode.mdc"
391 void code_node_print(FILE *out, struct code_node *node,
394 for (; node; node = node->next) {
395 char *c = node->code.txt;
396 int len = node->code.len;
401 fprintf(out, "#line %d \"%s\"\n",
402 node->line_no, fname);
404 if (node->indent >= 8)
405 fprintf(out, "\t%*s", node->indent - 8, "");
407 fprintf(out, "%*s", node->indent, "");
408 if (node->needs_strip) {
409 if (*c == '\t' && len > 1) {
412 } else if (strncmp(c, " ", 4) == 0 && len > 4) {
421 } while (len && c[-1] != '\n');
425 #line 115 "../mdcode.mdc"