diff --git a/Makefile b/Makefile index 8c534ab..230f132 100644 --- a/Makefile +++ b/Makefile @@ -1,8 +1,10 @@ -OBJ:= main.o +OBJ:= html.o main.o OUTPUT:=nhtmlc -debug: CXXFLAGS = -g -debug: CFLAGS = -g +all: debug + +debug: CXXFLAGS = -g -DDEBUG +debug: CFLAGS = -g -DDEBUG debug: $(OBJ) gcc $(OBJ) -g -o $(OUTPUT) diff --git a/main.c b/main.c index beae419..b4e95fa 100644 --- a/main.c +++ b/main.c @@ -2,6 +2,12 @@ #include // needs: realloc, malloc, free #include // needs: strcmp, memcpy #include +#include // needs: isspace + +#include // needs: getopt_long + +#include "html.h" // needs: html_escaped + typedef struct { char * c_str; size_t len; @@ -23,6 +29,7 @@ int string_append(string_t *str, char c) { str->c_str[str->len-1] = c; str->c_str[str->len] = 0; // make sure str->len++; + return 0; } void string_destroy(string_t s) { @@ -62,6 +69,8 @@ attr_t * attr_set_find(attr_set_t *set, const char * name) { // Append new Attribute to set int attr_set_append(attr_set_t * set, attr_t *new_entry) { + if (new_entry->name.c_str== NULL) return -1; // reject empty entries + // search first attr_t * new_ptr = attr_set_find(set, new_entry->name.c_str); if (new_ptr != NULL) { @@ -84,15 +93,90 @@ int attr_set_append(attr_set_t * set, attr_t *new_entry) { return 0; } +void attr_reset(attr_t * attr) { + memset(attr, 0, sizeof(attr_t)); +} + +int strip(FILE * stream) { + int current = 0; + while((current = fgetc(stream)) != EOF) { + if (!isspace(current)) + break; + } + + return current; +} + int parse_attr(FILE * stream, attr_set_t * output) { - fprintf(stderr, "stub: parse_attr\n"); - return 0; + attr_t current_attr = {}; +#ifdef DEBUG + printf("parse_attr\n"); +#endif + int buffer = 0; + unsigned char isKey = 1; + + while((buffer = fgetc(stream)) != EOF) { + // parse key=value pairs + // check for delim + //if (buffer == ' ' || buffer == '\t' || buffer == '\n'){ + if (isspace(buffer)) { + attr_set_append(output, ¤t_attr); +#ifdef DEBUG + printf("parsed attr: %s=%s\n", current_attr.name.c_str, current_attr.value); +#endif + // reset attribute + attr_reset(¤t_attr); + isKey = 1; + continue; + } + if (buffer == '=') { + isKey = 0; + continue; + } else + if (buffer == ']') { + break; + } + + if (isKey) { + string_append(¤t_attr.name, buffer); + } else { + string_append(¤t_attr.value, buffer); + } + } + + // append last attribute + attr_set_append(output, ¤t_attr); + + //memset(output, 0, sizeof(attr_set_t)); + return strip(stream); } int parse_text(FILE * stream, FILE * output) { - // STUB - fprintf(stderr, "stub: parse_text\n"); - return 0; +#ifdef DEBUG + printf("parse text\n"); +#endif + int buffer = 0; + char escaped = 0; + + while((buffer = fgetc(stream)) != EOF) { + if (!escaped && buffer == '\\') { + escaped = 1; + continue; + } + if (!escaped && buffer == '"') { + break; + } + escaped = 0; + + if (html_escape(buffer, output)) { + continue; + } + + fputc(buffer, output); + } + + //fprintf(stderr, "stub: parse_text\n"); + return strip(stream); } typedef struct node { @@ -102,7 +186,10 @@ typedef struct node { // write out node -void print_node(node_t * node, FILE * output) { +void open_node(node_t * node, FILE * output) { + // check for empty node (text mostly) + if (!node->name.c_str) return; + // start by writing tag fputc('<', output); @@ -113,43 +200,99 @@ void print_node(node_t * node, FILE * output) { size_t i = 0; attr_t * current = node->attributes.arr; for (; i < node->attributes.len; i++,current++) { - fprintf(output, " %s=\"%s\"", current->name.c_str, current->value.c_str); + if (current->value.c_str) + fprintf(output, " %s=\"%s\"", current->name.c_str, current->value.c_str); + else { + fputc(' ', output); + fputs(current->name.c_str, output); + } } // close tag fputc('>', output); } +void close_node(node_t * node, FILE * output) { + if (node->name.c_str) { + fprintf(output, "", node->name.c_str); + } +} -int print_tag(FILE * stream, FILE * output) { - node_t new_node; - int buffer = 0; - - while ((buffer = fgetc(stream)) != EOF) { - switch(buffer) { - case '[': // parse attributes - if (parse_attr(stream, &new_node.attributes) != -1) { - fprintf(stderr, "could not parse attributes: %d", -1); - return -1; - } - break; - case '"': - // raw text - parse_text(stream, output); - break; - default: - if (buffer != ' ' && buffer != '\t' && buffer != '\n') { - string_append(&new_node.name, buffer); - } - } +int readName(FILE *stream, node_t *node) { + int current = strip(stream); + if (current == EOF) { + return current; } - - return 0; + do { + if (current == '{' || current == '[') { + break; + } + + if (current == ' ' || current == '\t' || current == '\n') { + current = strip(stream); + break; + } + + string_append(&node->name, current); + } while((current = fgetc(stream)) != EOF); + + return current; +} + + +enum node_type { + NODE_SELFCLOSING, + NODE_TEXT, + NODE_TAG +}; + +int parse_node(int current, FILE * stream, FILE * output) { + if (current == '"') { + return parse_text(stream, output); + } + + // normal node + node_t current_node = {}; + string_append(¤t_node.name, current); + current = readName(stream, ¤t_node); + if (current == EOF) { + goto done; + } +#ifdef DEBUG + printf("parse_node: %s\n", current_node.name.c_str); +#endif + if (current == '[') { + current = parse_attr(stream, ¤t_node.attributes); + } + + if (current != '{') { + // tag is selfclosing + open_node(¤t_node, output); + return current; + } + current = strip(stream); + + open_node(¤t_node, output); + while(current != '}' && current != EOF) { + current = parse_node(current, stream, output); + } + + close_node(¤t_node, output); +done: + return strip(stream); } int main(int argc, char ** args) { + //getopt_long(argc, args, NULL, NULL, NULL); + char * filename= NULL; - for(;argc != 1; --argc) { + FILE * output = fopen("a.html", "w"); + if (output == NULL) { + fprintf(stderr, "could not create output file\n"); + return -1; + } + + for(;argc > 1; --argc) { filename = args[argc-1]; printf("starting conversion of %s\n", filename); @@ -160,16 +303,19 @@ int main(int argc, char ** args) { continue; } - while(!feof(handle)) { - if (print_tag(handle, stdout) != 0) { - fprintf(stderr, "error during parsing of node\n"); - break; - } + int current = strip(handle); + + while((current = parse_node(current, handle, output)) != EOF) { +// if () { +// fprintf(stderr, "error during parsing of node\n"); +// break; +// } } fclose(handle); } + fclose(output); printf("done compiling\n"); return 0; } diff --git a/test.nhtml b/test.nhtml index 3ca81ae..20a2918 100644 --- a/test.nhtml +++ b/test.nhtml @@ -1,12 +1,28 @@ -div { - "hi i'm raw text" - "I'm raw text too :)" - "Including \"escaping\"" -} -h1 { -div { - "Another, but bigger font" - "Adding a - new line adds a
:)" -} +!DOCTYPE[html] +head { + title { "was geht" } + meta[charset=utf-8] } +body { + h1 { "Alle Meine Endchen schwimmen auf dem See" } + p { + "Alle meine Entchen schwimmen auf dem See, + schwimmen auf dem See, + Köpfchen in das Wasser, Schwänzchen in die Höh'." + } + p { + "Alle meine Täubchen gurren auf dem Dach, + gurren auf dem Dach, + eins fliegt in die Lüfte, fliegen alle nach." + } + p { + "Alle meine Hühner scharren in dem Stroh, + scharren in dem Stroh, + finden sie ein Körnchen, sind sie alle froh." + } + p { + "Alle meine Gänschen watscheln durch den Grund, + watscheln durch den Grund, + suchen in dem Tümpel, werden kugelrund." + } +} \ No newline at end of file