X-Git-Url: https://git.danieliu.xyz/?a=blobdiff_plain;f=parser.c;h=1ff125c69775ca61ce981e10f5216a26ed7fbff3;hb=6edf0543111ac7f119c0255ae254159d9508f770;hp=0343509b5976f151884ecc123081689c3811bb34;hpb=4a1ae435f312e8d76558ef1e64f141ebffd15f9d;p=smdp.git
diff --git a/parser.c b/parser.c
index 0343509..1ff125c 100644
--- a/parser.c
+++ b/parser.c
@@ -1,21 +1,51 @@
+/*
+ * Functions necessary to parse a file and transform its content into
+ * a deck of slides containing lines. All based on markdown formating
+ * rules.
+ * Copyright (C) 2014 Michael Goehler
+ *
+ * This file is part of mdp.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+
+#include
#include
#include
#include "include/parser.h"
-document_t *markdown_load(FILE *input) {
+deck_t *markdown_load(FILE *input) {
- int c = 0, i = 0, bits = 0;
+ int c = 0; // char
+ int i = 0; // increment
+ int l = 0; // line length
+ int hc = 0; // header count
+ int lc = 0; // line count
+ int sc = 0; // slide count
+ int bits = 0; // markdown bits
- document_t *doc;
- page_t *page;
- line_t *line;
- cstring_t *text;
+ deck_t *deck = new_deck();
+ slide_t *slide = new_slide();
+ line_t *line = NULL;
+ line_t *tmp = NULL;
+ cstring_t *text = cstring_init();
- doc = new_document();
- page = new_page();
- doc->page = page;
- text = cstring_init();
+ // assign first slide to deck
+ deck->slide = slide;
+ sc++;
while ((c = fgetc(input)) != EOF) {
if(c == '\n') {
@@ -23,28 +53,41 @@ document_t *markdown_load(FILE *input) {
// markdown analyse
bits = markdown_analyse(text);
+ // if first line in file is markdown hr
+ if(!line && CHECK_BIT(bits, IS_HR)) {
+
+ // clear text
+ (text->reset)(text);
+
// if text is markdown hr
- if(CHECK_BIT(bits, IS_HR) &&
- CHECK_BIT(line->bits, IS_EMPTY)) {
+ } else if(CHECK_BIT(bits, IS_HR) &&
+ CHECK_BIT(line->bits, IS_EMPTY)) {
+
+ slide->lines = lc;
// clear text
(text->reset)(text);
- // create next page
- page = next_page(page);
+ l = 0;
+
+ // create next slide
+ slide = next_slide(slide);
+ sc++;
} else {
- // if page ! has line
- if(!page->line) {
+ // if slide ! has line
+ if(!slide->line) {
// create new line
line = new_line();
- page->line = line;
+ slide->line = line;
+ lc = 1;
} else {
// create next line
line = next_line(line);
+ lc++;
}
@@ -54,35 +97,83 @@ document_t *markdown_load(FILE *input) {
// add bits to line
line->bits = bits;
+ // add length to line
+ line->length = l;
+
// calc offset
line->offset = next_nonblank(text, 0);
// new text
text = cstring_init();
+ l = 0;
}
} else if(c == '\t') {
// expand tab to spaces
- for (i = 0; i <= 4; i++)
+ for (i = 0; i < EXPAND_TABS; i++) {
(text->expand)(text, ' ');
+ l++;
+ }
+
+ } else if(c == '\\') {
+
+ // add char to line
+ (text->expand)(text, c);
+ l++;
+
+ // if !IS_CODE add next char to line
+ // and do not increase line count
+ if(next_nonblank(text, 0) < CODE_INDENT) {
+
+ c = fgetc(input);
+ (text->expand)(text, c);
+
+ if(is_utf8(c)) {
+
+ // if utf-8 char > 1 byte add remaing to line
+ for(i = 0; i < length_utf8(c) - 1; i++) {
+ c = fgetc(input);
+ (text->expand)(text, c);
+ }
+ }
+
+ }
- } else if(isprint(c) || isspace(c) || is_utf8(c)) {
+ } else if(isprint(c) || isspace((unsigned char) c)) {
// add char to line
(text->expand)(text, c);
+ l++;
+
+ } else if(is_utf8(c)) {
+
+ // add char to line
+ (text->expand)(text, c);
+
+ // if utf-8 char > 1 byte add remaing to line
+ for(i = 0; i < length_utf8(c) - 1; i++) {
+ c = fgetc(input);
+ (text->expand)(text, c);
+ }
+
+ l++;
}
}
+ slide->lines = lc;
+ deck->slides = sc;
+
// detect header
- line = doc->page->line;
+ line = deck->slide->line;
if(line && line->text->size > 0 && line->text->text[0] == '%') {
- // assign header to document
- doc->header = line;
+ // assign header to deck
+ deck->header = line;
// find first non-header line
while(line->text->size > 0 && line->text->text[0] == '%') {
+ hc++;
line = line->next;
}
@@ -90,14 +181,18 @@ document_t *markdown_load(FILE *input) {
line->prev->next = (void*)0;
line->prev = (void*)0;
- // remove header lines from page
- doc->page->line = line;
+ // remove header lines from slide
+ deck->slide->line = line;
+
+ // adjust counts
+ deck->headers += hc;
+ deck->slide->lines -= hc;
}
// combine underlined H1/H2 in single line
- page = doc->page;
- while(page) {
- line = page->line;
+ slide = deck->slide;
+ while(slide) {
+ line = slide->line;
while(line) {
if((CHECK_BIT(line->bits, IS_H1) ||
CHECK_BIT(line->bits, IS_H2)) &&
@@ -107,49 +202,74 @@ document_t *markdown_load(FILE *input) {
// remove line from linked list
line->prev->next = line->next;
- line->next->prev = line->prev;
+ if(line->next)
+ line->next->prev = line->prev;
- // set bits on revious line
+ // set bits on previous line
if(CHECK_BIT(line->bits, IS_H1)) {
SET_BIT(line->prev->bits, IS_H1);
} else {
SET_BIT(line->prev->bits, IS_H2);
}
+ // adjust line count
+ slide->lines -= 1;
+
+ // maintain loop condition
+ tmp = line;
+ line = line->prev;
+
// delete line
- (line->text->delete)(line->text);
- free(line);
+ (tmp->text->delete)(tmp->text);
+ free(tmp);
}
line = line->next;
}
- page = page->next;
+ slide = slide->next;
}
- return doc;
+ return deck;
}
int markdown_analyse(cstring_t *text) {
- int i = 0, bits = 0,
- offset = 0, eol = 0,
- equals = 0, hashes = 0,
+
+ int i = 0; // increment
+ int bits = 0; // markdown bits
+ int offset = 0; // text offset
+ int eol = 0; // end of line
+
+ int equals = 0, hashes = 0,
stars = 0, minus = 0,
- spaces = 0, other = 0;
+ spaces = 0, other = 0; // special character counts
// count leading spaces
offset = next_nonblank(text, 0);
// strip trailing spaces
- for(eol = text->size; eol > offset && isspace(text->text[eol - 1]); eol--);
+ for(eol = text->size; eol > offset && isspace((unsigned char) text->text[eol - 1]); eol--);
+
+ // IS_CODE
+ if(offset >= CODE_INDENT) {
+ SET_BIT(bits, IS_CODE);
+ }
for(i = offset; i < eol; i++) {
- switch(text->text[i]) {
- case '=': equals++; break;
- case '#': hashes++; break;
- case '*': stars++; break;
- case '-': minus++; break;
- case ' ': spaces++; break;
- default: other++; break;
+ if(text->text[i] == ' ') {
+ spaces++;
+
+ } else if(CHECK_BIT(bits, IS_CODE)) {
+ other++;
+
+ } else {
+ switch(text->text[i]) {
+ case '=': equals++; break;
+ case '#': hashes++; break;
+ case '*': stars++; break;
+ case '-': minus++; break;
+ case '\\': other++; i++; break;
+ default: other++; break;
+ }
}
}
@@ -183,11 +303,6 @@ int markdown_analyse(cstring_t *text) {
SET_BIT(bits, IS_QUOTE);
}
- // IS_CODE
- if(offset >= 4) {
- SET_BIT(bits, IS_CODE);
- }
-
// IS_HR
if((minus >= 3 && equals + hashes + stars + other == 0) ||
(stars >= 3 && equals + hashes + minus + other == 0)) {
@@ -203,19 +318,93 @@ int markdown_analyse(cstring_t *text) {
return bits;
}
+void markdown_debug(deck_t *deck, int debug) {
+
+ int sc = 0; // slide count
+ int lc = 0; // line count
+
+ int offset;
+ line_t *header;
+
+ if(debug == 1) {
+ fprintf(stderr, "headers: %i\nslides: %i\n", deck->headers, deck->slides);
+
+ } else if(debug > 1) {
+
+ // print header to STDERR
+ if(deck->header) {
+ header = deck->header;
+ while(header &&
+ header->length > 0 &&
+ header->text->text[0] == '%') {
+
+ // skip descriptor word (e.g. %title:)
+ offset = next_blank(header->text, 0) + 1;
+
+ fprintf(stderr, "header: %s\n", &header->text->text[offset]);
+ header = header->next;
+ }
+ }
+ }
+
+ slide_t *slide = deck->slide;
+ line_t *line;
+
+ // print slide/line count to STDERR
+ while(slide) {
+ sc++;
+
+ if(debug == 1) {
+ fprintf(stderr, " slide %i: %i lines\n", sc, slide->lines);
+
+ } else if(debug > 1) {
+
+ // also print bits and line length
+ fprintf(stderr, " slide %i:\n", sc);
+ line = slide->line;
+ lc = 0;
+ while(line) {
+ lc++;
+ fprintf(stderr, " line %i: bits = %i, length = %i\n", lc, line->bits, line->length);
+ line = line->next;
+ }
+ }
+
+ slide = slide->next;
+ }
+}
+
int is_utf8(char ch) {
return (ch & 0x80);
}
+int length_utf8(char ch) {
+
+ int i = 0; // increment
+
+ while(ch & 0x80) {
+ i++;
+ ch <<= 1;
+ }
+
+ return i;
+}
+
int next_nonblank(cstring_t *text, int i) {
- while ((i < text->size) && isspace((text->text)[i]))
+ while ((i < text->size) && isspace((unsigned char) (text->text)[i]))
++i;
+
return i;
-};
+}
int next_blank(cstring_t *text, int i) {
- while ((i < text->size) && !isspace((text->text)[i]))
+ while ((i < text->size) && !isspace((unsigned char) (text->text)[i]))
++i;
+
return i;
-};
+}
+
+int next_word(cstring_t *text, int i) {
+ return next_nonblank(text, next_blank(text, i));
+}