added useful readme and added includes
This commit is contained in:
parent
381bd6acff
commit
7fe73e879e
75
README.md
75
README.md
@ -1,3 +1,76 @@
|
|||||||
# nhtml
|
# nhtml
|
||||||
|
|
||||||
Not html, a very simple template engine
|
!html, a very simple template language
|
||||||
|
|
||||||
|
Syntax
|
||||||
|
------------
|
||||||
|
As said above, the Template Language is simple.
|
||||||
|
That also implies a few limitations:
|
||||||
|
1. No Parametric instantiation (for now) since this would bloat the compiler too much
|
||||||
|
(I was in no need for that feature when writing this compiler).
|
||||||
|
2. No language integration of any kind.
|
||||||
|
This makes this template compiler useful for static webcontent only!
|
||||||
|
|
||||||
|
Sooo, how does it work?
|
||||||
|
* text enclosed with `""` will be placed in the html output, but will be html escaped and `\n` will be replaced with `<br/>`.
|
||||||
|
|
||||||
|
* text enclosed with () will be placed *without any changes*.
|
||||||
|
|
||||||
|
* One can include other files by writing either
|
||||||
|
`@<filename>`, e.g. `@hi.nhtml` or
|
||||||
|
`@"<filename>"`, e.g. `@"filename with spaces.nhtml"`
|
||||||
|
These files will pe pasted in place unless they end with `.nhtml`, in which case
|
||||||
|
they get compiled before getting pasted.
|
||||||
|
|
||||||
|
* There are comment blocks (`/*text*/`) and linecomments (`//text`) like there are in C.
|
||||||
|
|
||||||
|
* A left curly brace (`{`) opens a tag, a coresponding right curly brace (`}`) closes it.
|
||||||
|
|
||||||
|
* Finally, tag names are simply written as text and can be accompied by an attribute set
|
||||||
|
enclosed in `[]`. So in order to e.g. produce
|
||||||
|
`<div style="color:white">Hi</div>`, the corresponding nhtml would look something like
|
||||||
|
`div[style=color:white]{"Hi"}`.
|
||||||
|
|
||||||
|
* If the Attributes Key-Name is `class`, its pair can be written as `.<value>` instead of `class=<value>`.
|
||||||
|
Note that multiple mentions of the same attribute key will result in the attribute values
|
||||||
|
beeing concatenated with a space. So e.g.
|
||||||
|
`p[.A class=hi]{}` will become `<p class="A hi"></p>`.
|
||||||
|
|
||||||
|
That about covers everything this little thing can do :)
|
||||||
|
For a simple demo, look in example.
|
||||||
|
|
||||||
|
How to compile
|
||||||
|
--------------
|
||||||
|
|
||||||
|
The Project used cmake to build. It has no hard dependencies but it requires unix-style pathnames. (`/path/to/file`) for includes to work.
|
||||||
|
|
||||||
|
## on linux
|
||||||
|
Simply install cmake for your distro
|
||||||
|
### Ubuntu
|
||||||
|
`apt-get install cmake`
|
||||||
|
### Arch Linux
|
||||||
|
`pacman -S cmake`
|
||||||
|
|
||||||
|
The create a subdirectory for the build to reside in
|
||||||
|
`mkdir build`
|
||||||
|
`cd build`
|
||||||
|
|
||||||
|
And run cmake
|
||||||
|
Release: `cmake -G"Unix Makefiles" ..`
|
||||||
|
Debug: `cmake -G"Unix Makefiles" .. -DCMAKE_BUILD_TYPE=DEBUG`
|
||||||
|
|
||||||
|
after that run `make` and you should be left with a compiled version of the !html compiler `nhtmlc`
|
||||||
|
|
||||||
|
How to use
|
||||||
|
----------
|
||||||
|
```
|
||||||
|
./nhtmlc [-o <filename>] file [file...]
|
||||||
|
-I Add Path to include paths
|
||||||
|
--output
|
||||||
|
-o The output file to write the html to
|
||||||
|
When missing this option, stdout is used instead
|
||||||
|
-v Enable verbose output
|
||||||
|
--help Print this usage
|
||||||
|
```
|
||||||
|
|
||||||
|
When given multple input files, the resulting html is concatenated into output.
|
||||||
|
15
example/Makefile
Normal file
15
example/Makefile
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
|
||||||
|
all: entchen.html
|
||||||
|
|
||||||
|
NHTMLC:=../build/nhtmlc
|
||||||
|
|
||||||
|
%.html: %.nhtml
|
||||||
|
$(NHTMLC) $< -o $@
|
||||||
|
|
||||||
|
index.html: head.nhtml entchen.nhtml
|
||||||
|
$(NHTMLC) entchen.nhtml -o $@
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f entchen.html
|
||||||
|
|
||||||
|
.PHONY: all clean
|
9
example/entchen.css
Normal file
9
example/entchen.css
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
.strophe {
|
||||||
|
border-width:1px;
|
||||||
|
border-type:solid;
|
||||||
|
border-color:black;
|
||||||
|
background-color:gray;
|
||||||
|
font-type:italic;
|
||||||
|
color: white;
|
||||||
|
padding: 0.5em;
|
||||||
|
}
|
35
example/entchen.nhtml
Normal file
35
example/entchen.nhtml
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* Generates the body of our document
|
||||||
|
*
|
||||||
|
* File created by Julian Daube
|
||||||
|
* date: 08.08.2017
|
||||||
|
*/
|
||||||
|
|
||||||
|
@head.nhtml
|
||||||
|
body {
|
||||||
|
style {
|
||||||
|
@entchen.css
|
||||||
|
}
|
||||||
|
|
||||||
|
h3{ "Alle meine Entchen" }
|
||||||
|
p[.strophe] {
|
||||||
|
"Alle meine Entchen schwimmen auf dem See,
|
||||||
|
schwimmen auf dem See,
|
||||||
|
Köpfchen in das Wasser, Schwänzchen in die Höh'."
|
||||||
|
}
|
||||||
|
p[.strophe] {
|
||||||
|
"Alle meine Täubchen gurren auf dem Dach,
|
||||||
|
gurren auf dem Dach,
|
||||||
|
eins fliegt in die Lüfte, fliegen alle nach."
|
||||||
|
}
|
||||||
|
p[.strophe] {
|
||||||
|
"Alle meine Hühner scharren in dem Stroh,
|
||||||
|
scharren in dem Stroh,
|
||||||
|
finden sie ein Körnchen, sind sie alle froh."
|
||||||
|
}
|
||||||
|
p[.strophe] {
|
||||||
|
"Alle meine Gänschen watscheln durch den Grund,
|
||||||
|
watscheln durch den Grund,
|
||||||
|
suchen in dem Tümpel, werden kugelrund."
|
||||||
|
}
|
||||||
|
}
|
11
example/head.nhtml
Normal file
11
example/head.nhtml
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
/*
|
||||||
|
* Generates the document header
|
||||||
|
*
|
||||||
|
* file generated by Julian Daube
|
||||||
|
* date: 08.08.2017
|
||||||
|
*/
|
||||||
|
!DOCTYPE[html]
|
||||||
|
head {
|
||||||
|
title { "Alle meine Entchen" }
|
||||||
|
meta[charset=utf-8]
|
||||||
|
}
|
18
inc/includes.h
Normal file
18
inc/includes.h
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
/*
|
||||||
|
* includes.h
|
||||||
|
*
|
||||||
|
* Created on: 08.08.2017
|
||||||
|
* Author: julian
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef INC_INCLUDES_H_
|
||||||
|
#define INC_INCLUDES_H_
|
||||||
|
|
||||||
|
#include <nhtml_string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
void include_add_path(const char * path);
|
||||||
|
|
||||||
|
int include_file(string_t *filename, FILE * output);
|
||||||
|
|
||||||
|
#endif /* INC_INCLUDES_H_ */
|
@ -24,10 +24,18 @@ typedef struct {
|
|||||||
*/
|
*/
|
||||||
int string_append(string_t *str, char c);
|
int string_append(string_t *str, char c);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief append src to dest
|
||||||
|
* will enlarge dest to accommodate src
|
||||||
|
* \return -1 on failure (check errno)
|
||||||
|
* \return 0 on success
|
||||||
|
*/
|
||||||
|
int string_concat(string_t * dest, string_t * src);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Erase the String from memory
|
* \brief Erase the String from memory
|
||||||
*/
|
*/
|
||||||
void string_destroy(string_t s);
|
void string_destroy(string_t *s);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief copy the contents of a string
|
* \brief copy the contents of a string
|
||||||
@ -36,5 +44,10 @@ void string_destroy(string_t s);
|
|||||||
*/
|
*/
|
||||||
string_t string_copy(string_t old);
|
string_t string_copy(string_t old);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief creates copy of str
|
||||||
|
* \return a copy of str
|
||||||
|
*/
|
||||||
|
string_t string_from_cstr(const char * str);
|
||||||
|
|
||||||
#endif /* NHTML_STRING_H_ */
|
#endif /* NHTML_STRING_H_ */
|
||||||
|
17
inc/parser.h
Normal file
17
inc/parser.h
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
/*
|
||||||
|
* parser.h
|
||||||
|
*
|
||||||
|
* Created on: 08.08.2017
|
||||||
|
* Author: julian
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef INC_PARSER_H_
|
||||||
|
#define INC_PARSER_H_
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
int strip(FILE * input);
|
||||||
|
int parse_node(int current, FILE * stream, FILE * output);
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* INC_PARSER_H_ */
|
@ -5,4 +5,5 @@ set(SOURCE
|
|||||||
${pwd}/nhtml_string.c
|
${pwd}/nhtml_string.c
|
||||||
${pwd}/attribute.c
|
${pwd}/attribute.c
|
||||||
${pwd}/html.c
|
${pwd}/html.c
|
||||||
|
${pwd}/includes.c
|
||||||
PARENT_SCOPE)
|
PARENT_SCOPE)
|
||||||
|
@ -31,9 +31,10 @@ int attr_set_append(attr_set_t * set, attr_t *new_entry) {
|
|||||||
attr_t * new_ptr = attr_set_find(set, new_entry->name.c_str);
|
attr_t * new_ptr = attr_set_find(set, new_entry->name.c_str);
|
||||||
if (new_ptr != NULL) {
|
if (new_ptr != NULL) {
|
||||||
// already contained in set
|
// already contained in set
|
||||||
// just change entries value
|
// concatenate values
|
||||||
string_destroy(new_ptr->value);
|
//new_ptr->value = string_copy(new_entry->value);
|
||||||
new_ptr->value = string_copy(new_entry->value);
|
string_append(&new_ptr->value, ' ');
|
||||||
|
string_concat(&new_ptr->value, &new_entry->value);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -58,11 +59,8 @@ attr_t attr_copy(attr_t * attr) {
|
|||||||
|
|
||||||
void attr_destroy(attr_t * attr) {
|
void attr_destroy(attr_t * attr) {
|
||||||
// clear memory
|
// clear memory
|
||||||
string_destroy(attr->name);
|
string_destroy(&attr->name);
|
||||||
string_destroy(attr->value);
|
string_destroy(&attr->value);
|
||||||
|
|
||||||
// reset memory content
|
|
||||||
memset(attr, 0, sizeof(attr_t));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
94
src/includes.c
Normal file
94
src/includes.c
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
/*
|
||||||
|
* includes.c
|
||||||
|
*
|
||||||
|
* Created on: 08.08.2017
|
||||||
|
* Author: julian
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <includes.h>
|
||||||
|
#include <parser.h>
|
||||||
|
#include <nhtml_string.h>
|
||||||
|
#include <stdlib.h> // needs: malloc, realloc
|
||||||
|
#include <memory.h> // needs: memcpy
|
||||||
|
|
||||||
|
string_t* include_paths;
|
||||||
|
size_t num_includes = 0;
|
||||||
|
|
||||||
|
void include_paths_init() {
|
||||||
|
include_paths = malloc(sizeof(string_t));
|
||||||
|
num_includes = 1;
|
||||||
|
|
||||||
|
include_paths[0] = string_from_cstr("."); // search in current dir by default
|
||||||
|
}
|
||||||
|
|
||||||
|
const char * extension(const string_t * path) {
|
||||||
|
int i;
|
||||||
|
for (i = path->len; i > 0; i--) {
|
||||||
|
if (path->c_str[i] == '/')
|
||||||
|
return NULL;
|
||||||
|
if (path->c_str[i] == '.')
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return path->c_str + i;
|
||||||
|
}
|
||||||
|
|
||||||
|
void include_add_path(const char * path) {
|
||||||
|
if (num_includes == 0) {
|
||||||
|
include_paths_init();
|
||||||
|
}
|
||||||
|
|
||||||
|
include_paths = realloc(include_paths, sizeof(const char*)*(num_includes+1));
|
||||||
|
include_paths[num_includes] = string_from_cstr(path);
|
||||||
|
num_includes++;
|
||||||
|
}
|
||||||
|
|
||||||
|
int include_file(string_t *filename, FILE * output) {
|
||||||
|
FILE * input = NULL;
|
||||||
|
char * tempPath = NULL;
|
||||||
|
|
||||||
|
if(num_includes == 0) {
|
||||||
|
include_paths_init();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < num_includes; ++i) {
|
||||||
|
// actual length is length + 2 (2* end char)
|
||||||
|
tempPath = malloc(filename->len + include_paths[i].len);
|
||||||
|
if (tempPath == NULL) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Concatenate the two paths
|
||||||
|
// adding a safety slash to separate the two
|
||||||
|
memcpy(tempPath, include_paths[i].c_str, include_paths[i].len-1);
|
||||||
|
tempPath[include_paths->len-1] = '/';
|
||||||
|
memcpy(tempPath + include_paths->len, filename->c_str, filename->len);
|
||||||
|
|
||||||
|
input = fopen(tempPath, "r");
|
||||||
|
if (input != NULL) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (input == NULL) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
const char * ext = extension(filename);
|
||||||
|
#ifdef DEBUG
|
||||||
|
printf("include %s, ext: %s\n", filename->c_str, ext);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (ext && !strcmp(ext, ".nhtml")) {
|
||||||
|
// (re)parse whole file
|
||||||
|
int current = strip(input);
|
||||||
|
while((current = parse_node(current, input, output)) != EOF);
|
||||||
|
} else {
|
||||||
|
// copy file 1:1
|
||||||
|
int current = 0;
|
||||||
|
while((current = fgetc(input)) != EOF) {
|
||||||
|
fputc(current, output);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fclose(input);
|
||||||
|
return 1;
|
||||||
|
}
|
128
src/main.c
128
src/main.c
@ -7,9 +7,14 @@
|
|||||||
#include <getopt.h> // needs: getopt_long
|
#include <getopt.h> // needs: getopt_long
|
||||||
|
|
||||||
// Project specific includes
|
// Project specific includes
|
||||||
#include "html.h"
|
#include <html.h>
|
||||||
#include "attribute.h"
|
#include <attribute.h>
|
||||||
#include "nhtml_string.h"
|
#include <nhtml_string.h>
|
||||||
|
#include <includes.h>
|
||||||
|
|
||||||
|
// globals
|
||||||
|
|
||||||
|
int verbose = 0;
|
||||||
|
|
||||||
int strip(FILE * stream) {
|
int strip(FILE * stream) {
|
||||||
int current = 0;
|
int current = 0;
|
||||||
@ -45,8 +50,7 @@ int parse_attr(FILE * stream, attr_set_t * output) {
|
|||||||
}
|
}
|
||||||
if (isKey && buffer == '.') {
|
if (isKey && buffer == '.') {
|
||||||
isKey = 0;
|
isKey = 0;
|
||||||
current_attr.name.c_str = "class";
|
current_attr.name = string_from_cstr("class");
|
||||||
current_attr.name.len = 6;
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (buffer == '=') {
|
if (buffer == '=') {
|
||||||
@ -70,7 +74,7 @@ int parse_attr(FILE * stream, attr_set_t * output) {
|
|||||||
printf("parsed attr: %s=%s\n", current_attr.name.c_str, current_attr.value);
|
printf("parsed attr: %s=%s\n", current_attr.name.c_str, current_attr.value);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//memset(output, 0, sizeof(attr_set_t));
|
attr_destroy(¤t_attr);
|
||||||
return strip(stream);
|
return strip(stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -122,11 +126,102 @@ int readName(FILE *stream, node_t *node) {
|
|||||||
return current;
|
return current;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Parse comments
|
||||||
|
int parse_comment(int current, FILE * input) {
|
||||||
|
current = fgetc(input);
|
||||||
|
if (current == '/') {
|
||||||
|
// line comment
|
||||||
|
while((current = fgetc(input)) != EOF) {
|
||||||
|
if (current == '\n') break;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
if (current == '*') {
|
||||||
|
// block comment
|
||||||
|
unsigned char comment_done = 0;
|
||||||
|
while((current = fgetc(input)) != EOF) {
|
||||||
|
if (current == '*') {
|
||||||
|
comment_done = 1;
|
||||||
|
} else
|
||||||
|
if (comment_done && current == '/') {
|
||||||
|
break;
|
||||||
|
} else
|
||||||
|
comment_done = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return strip(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
int parse_include(FILE * input, FILE * output) {
|
||||||
|
// handle include
|
||||||
|
int current = fgetc(input);
|
||||||
|
string_t filename = {};
|
||||||
|
|
||||||
|
// two possibilities
|
||||||
|
// 1. include with "" <= supports arbitrary paths
|
||||||
|
// 2. include without ""
|
||||||
|
// reads till a nonpath, char (!{")
|
||||||
|
// then strips empty chars from start and end of path
|
||||||
|
// both methods then try to find the file in the include paths
|
||||||
|
if (current == EOF) return current;
|
||||||
|
|
||||||
|
if (current == '"') { // Method 1
|
||||||
|
char escaped = 0;
|
||||||
|
while((current = fgetc(input)) != EOF) {
|
||||||
|
if (!escaped && current == '\\') {
|
||||||
|
escaped = 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!escaped && current == '"') {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
escaped = 0;
|
||||||
|
string_append(&filename, current);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
string_append(&filename, current);
|
||||||
|
while((current = fgetc(input)) != EOF) {
|
||||||
|
switch(current) {
|
||||||
|
case '{':
|
||||||
|
case '!':
|
||||||
|
case '"':
|
||||||
|
case '}':
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (isspace(current)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
string_append(&filename, current);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (filename.c_str == NULL) {
|
||||||
|
fprintf(stderr, "include command without filename!\n");
|
||||||
|
return strip(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
// handle filename
|
||||||
|
if (verbose) printf("include file %s\n", filename.c_str);
|
||||||
|
|
||||||
|
if (!include_file(&filename, output)) {
|
||||||
|
fprintf(stderr, "could not include file %s\n", filename.c_str);
|
||||||
|
}
|
||||||
|
|
||||||
|
return strip(input);
|
||||||
|
}
|
||||||
|
|
||||||
int parse_node(int current, FILE * stream, FILE * output) {
|
int parse_node(int current, FILE * stream, FILE * output) {
|
||||||
if (current == '"' || current == '(') {
|
if (current == '"' || current == '(') {
|
||||||
if (current == '(') current = ')';
|
if (current == '(') current = ')';
|
||||||
|
|
||||||
return parse_text(current, stream, output);
|
return parse_text(current, stream, output);
|
||||||
|
} else
|
||||||
|
if (current == '/') {
|
||||||
|
return parse_comment(current, stream);
|
||||||
|
} else
|
||||||
|
if (current == '@') {
|
||||||
|
return parse_include(stream, output);
|
||||||
}
|
}
|
||||||
|
|
||||||
// normal node
|
// normal node
|
||||||
@ -161,6 +256,7 @@ done:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// long options
|
// long options
|
||||||
static struct option long_options[] = {
|
static struct option long_options[] = {
|
||||||
{"output", required_argument, 0, 'o'},
|
{"output", required_argument, 0, 'o'},
|
||||||
@ -168,13 +264,14 @@ static struct option long_options[] = {
|
|||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
int verbose = 1;
|
|
||||||
|
|
||||||
void usage(int argc, char ** args) {
|
void usage(int argc, char ** args) {
|
||||||
printf("usage: %s [-o <filename>] file [file...]\n", args[0]);
|
printf("usage: %s [-o <filename>] file [file...]\n", args[0]);
|
||||||
|
printf("-I\tAdd Path to include paths\n");
|
||||||
printf("--output\n");
|
printf("--output\n");
|
||||||
printf("-o\tThe output file to write the html to\n");
|
printf("-o\tThe output file to write the html to\n");
|
||||||
printf("\tWhen missing this option, stdout is used instead\n");
|
printf("\tWhen missing this option, stdout is used instead\n");
|
||||||
|
printf("-v\tEnable verbose output\n");
|
||||||
printf("--help Print this usage\n");
|
printf("--help Print this usage\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -183,16 +280,22 @@ int main(int argc, char ** args) {
|
|||||||
FILE* output = NULL;
|
FILE* output = NULL;
|
||||||
|
|
||||||
// parse arguments
|
// parse arguments
|
||||||
while((i = getopt_long(argc, args, "o:v", long_options, NULL)) != -1) {
|
while((i = getopt_long(argc, args, "o:I:v", long_options, NULL)) != -1) {
|
||||||
switch(i) {
|
switch(i) {
|
||||||
case 'o':
|
case 'o':
|
||||||
printf("output: %s\n", optarg);
|
|
||||||
output = fopen(optarg, "w");
|
output = fopen(optarg, "w");
|
||||||
if (output == NULL) {
|
if (output == NULL) {
|
||||||
fprintf(stderr, "could not create file: %s\n", strerror(errno));
|
fprintf(stderr, "could not create output file: %s (%s)\n", optarg, strerror(errno));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case 'I':
|
||||||
|
// add include dir
|
||||||
|
include_add_path(optarg);
|
||||||
|
break;
|
||||||
|
case 'v':
|
||||||
|
verbose = 1;
|
||||||
|
break;
|
||||||
case '?':
|
case '?':
|
||||||
usage(argc, args);
|
usage(argc, args);
|
||||||
return -1;
|
return -1;
|
||||||
@ -204,6 +307,7 @@ int main(int argc, char ** args) {
|
|||||||
|
|
||||||
if (output == NULL) {
|
if (output == NULL) {
|
||||||
output = stdout;
|
output = stdout;
|
||||||
|
// disable output when printing to stdout
|
||||||
verbose = 0;
|
verbose = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -211,7 +315,7 @@ int main(int argc, char ** args) {
|
|||||||
|
|
||||||
// parse all the files
|
// parse all the files
|
||||||
for(i = optind;i < argc; i++) {
|
for(i = optind;i < argc; i++) {
|
||||||
filename = args[argc-1];
|
filename = args[i];
|
||||||
if (verbose) printf("starting conversion of %s\n", filename);
|
if (verbose) printf("starting conversion of %s\n", filename);
|
||||||
|
|
||||||
FILE * handle = fopen(filename, "r");
|
FILE * handle = fopen(filename, "r");
|
||||||
|
@ -7,7 +7,8 @@
|
|||||||
|
|
||||||
#include "nhtml_string.h"
|
#include "nhtml_string.h"
|
||||||
#include <stdlib.h> // needs: malloc, free
|
#include <stdlib.h> // needs: malloc, free
|
||||||
#include <memory.h> // needs: memcpy
|
#include <memory.h> // needs: memcpy, memset
|
||||||
|
#include <string.h> // needs: strlen, strdup
|
||||||
|
|
||||||
int string_append(string_t *str, char c) {
|
int string_append(string_t *str, char c) {
|
||||||
if (str->c_str == NULL) {
|
if (str->c_str == NULL) {
|
||||||
@ -29,12 +30,35 @@ int string_append(string_t *str, char c) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void string_destroy(string_t s) {
|
int string_concat(string_t * dest, string_t *src) {
|
||||||
free(s.c_str);
|
if (src->c_str == NULL) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dest->c_str == NULL) {
|
||||||
|
dest->len++;
|
||||||
|
}
|
||||||
|
|
||||||
|
char * new_ptr = realloc(dest->c_str, dest->len + src->len-1);
|
||||||
|
if (new_ptr == NULL) {
|
||||||
|
errno = ENOMEM;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(dest->c_str + dest->len-1, src->c_str, src->len);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void string_destroy(string_t *s) {
|
||||||
|
free(s->c_str);
|
||||||
|
memset(s, 0, sizeof(string_t));
|
||||||
}
|
}
|
||||||
|
|
||||||
string_t string_copy(string_t old) {
|
string_t string_copy(string_t old) {
|
||||||
string_t tmp = {}; // initialize with 0
|
string_t tmp = {}; // initialize with 0
|
||||||
|
if (old.len == 0) {
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
tmp.c_str = malloc(old.len);
|
tmp.c_str = malloc(old.len);
|
||||||
if (tmp.c_str == NULL) {
|
if (tmp.c_str == NULL) {
|
||||||
@ -48,3 +72,9 @@ string_t string_copy(string_t old) {
|
|||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string_t string_from_cstr(const char * str) {
|
||||||
|
string_t temp;
|
||||||
|
temp.len = strlen(str)+1;
|
||||||
|
temp.c_str = strdup(str);
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user