Added auto escape
This commit is contained in:
106
README.md
Normal file
106
README.md
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
# natechoe.dev generator
|
||||||
|
|
||||||
|
A very simple tool to generate natechoe.dev pages. It's effectively just a
|
||||||
|
generic file preprocessor with HTML some auto escaping.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
There are only 3 features in ncdg:
|
||||||
|
|
||||||
|
### Include statements
|
||||||
|
|
||||||
|
file1.html
|
||||||
|
|
||||||
|
```
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset='utf-8'>
|
||||||
|
<link rel='stylesheet' href='/resources/style.css'>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
@%file2.html@
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
```
|
||||||
|
|
||||||
|
file2.html
|
||||||
|
|
||||||
|
```
|
||||||
|
<h1>Title!</h1>
|
||||||
|
<p>Content!</p>
|
||||||
|
```
|
||||||
|
|
||||||
|
Result:
|
||||||
|
|
||||||
|
```
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset='utf-8'>
|
||||||
|
<link rel='stylesheet' href='/resources/style.css'>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>Title!</h1>
|
||||||
|
<p>Content!</p>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
```
|
||||||
|
|
||||||
|
### Variables
|
||||||
|
|
||||||
|
file1.html
|
||||||
|
|
||||||
|
```
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset='utf-8'>
|
||||||
|
<link rel='stylesheet' href='/resources/style.css'>
|
||||||
|
<title>%!title%</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>@!title@</h1>
|
||||||
|
@%file2.html@
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
```
|
||||||
|
|
||||||
|
file2.html
|
||||||
|
|
||||||
|
```
|
||||||
|
@=title Title!@
|
||||||
|
<p>Content!</p>
|
||||||
|
```
|
||||||
|
|
||||||
|
Result:
|
||||||
|
|
||||||
|
```
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset='utf-8'>
|
||||||
|
<link rel='stylesheet' href='/resources/style.css'>
|
||||||
|
<title>Title!</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>Title!</h1>
|
||||||
|
<p>Content!</p>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
```
|
||||||
|
|
||||||
|
### Automatic escaping
|
||||||
|
|
||||||
|
```
|
||||||
|
<pre><code>%\
|
||||||
|
#include <stdio.h>
|
||||||
|
%</code></pre>
|
||||||
|
```
|
||||||
|
|
||||||
|
Result:
|
||||||
|
|
||||||
|
```
|
||||||
|
<pre><code>
|
||||||
|
#include <stdio.h%gt;
|
||||||
|
</code></pre>
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
#define ESCAPE_CHAR '%'
|
#define ESCAPE_CHAR '@'
|
||||||
#define INCLUDE_CHAR '@'
|
#define INCLUDE_CHAR '%'
|
||||||
#define VAR_CHAR '>'
|
#define VAR_CHAR '!'
|
||||||
#define SET_CHAR '='
|
#define SET_CHAR '='
|
||||||
|
#define AUTOESCAPE_CHAR '\\'
|
||||||
|
|
||||||
#define MAX_INCLUDE_DEPTH 10
|
#define MAX_INCLUDE_DEPTH 10
|
||||||
|
|||||||
97
src/parse.c
97
src/parse.c
@@ -19,43 +19,65 @@ struct expandfile {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static int expandfile(struct expandfile *ret, char *filename, int level);
|
static int expandfile(struct expandfile *ret, char *filename, int level);
|
||||||
|
static int writefile(struct expandfile *file, FILE *out);
|
||||||
static struct string *getstring(FILE *file, char end);
|
static struct string *getstring(FILE *file, char end);
|
||||||
|
|
||||||
int parsefile(char *template, FILE *out) {
|
int parsefile(char *template, FILE *out) {
|
||||||
struct expandfile *expanded;
|
struct expandfile expanded;
|
||||||
expanded = malloc(sizeof *expanded);
|
int ret;
|
||||||
if (expanded == NULL)
|
expanded.data = newstring();
|
||||||
|
if (expanded.data == NULL) {
|
||||||
|
ret = 1;
|
||||||
goto error1;
|
goto error1;
|
||||||
expanded->data = newstring();
|
}
|
||||||
if (expanded->data == NULL)
|
expanded.vars = newvector(struct var);
|
||||||
|
if (expanded.vars == NULL) {
|
||||||
|
ret = 1;
|
||||||
goto error2;
|
goto error2;
|
||||||
expanded->vars = newvector(struct var);
|
}
|
||||||
if (expanded->vars == NULL)
|
if (expandfile(&expanded, template, 0)) {
|
||||||
|
ret = 1;
|
||||||
goto error3;
|
goto error3;
|
||||||
if (expandfile(expanded, template, 0))
|
}
|
||||||
goto error4;
|
ret = writefile(&expanded, out);
|
||||||
|
error3:
|
||||||
{
|
{
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < expanded.vars->len; ++i) {
|
||||||
|
struct var var;
|
||||||
|
var = getvector(expanded.vars, struct var, i);
|
||||||
|
freestring(var.var);
|
||||||
|
freestring(var.value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
freevector(expanded.vars);
|
||||||
|
error2:
|
||||||
|
freestring(expanded.data);
|
||||||
|
error1:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int writefile(struct expandfile *file, FILE *out) {
|
||||||
long i;
|
long i;
|
||||||
for (i = 0; i < expanded->data->len; ++i) {
|
for (i = 0; i < file->data->len; ++i) {
|
||||||
if (expanded->data->data[i] == ESCAPE_CHAR) {
|
if (file->data->data[i] == ESCAPE_CHAR) {
|
||||||
switch (expanded->data->data[++i]) {
|
const struct string *data = file->data;
|
||||||
|
const struct vector *vars = file->vars;
|
||||||
|
switch (data->data[++i]) {
|
||||||
case ESCAPE_CHAR:
|
case ESCAPE_CHAR:
|
||||||
fputc(ESCAPE_CHAR, out);
|
fputc(ESCAPE_CHAR, out);
|
||||||
break;
|
break;
|
||||||
case VAR_CHAR: {
|
case VAR_CHAR: {
|
||||||
long start;
|
long start;
|
||||||
int j;
|
int j;
|
||||||
struct string *data;
|
|
||||||
struct vector *vars;
|
|
||||||
char *varname;
|
char *varname;
|
||||||
data = expanded->data;
|
|
||||||
start = ++i;
|
start = ++i;
|
||||||
while (data->data[i] != ESCAPE_CHAR &&
|
while (data->data[i] != ESCAPE_CHAR &&
|
||||||
i < data->len)
|
i < data->len)
|
||||||
++i;
|
++i;
|
||||||
data->data[i] = '\0';
|
data->data[i] = '\0';
|
||||||
varname = data->data + start;
|
varname = data->data + start;
|
||||||
vars = expanded->vars;
|
vars = file->vars;
|
||||||
for (j = 0; j < vars->len; ++j) {
|
for (j = 0; j < vars->len; ++j) {
|
||||||
struct var var;
|
struct var var;
|
||||||
var = getvector(vars,
|
var = getvector(vars,
|
||||||
@@ -67,30 +89,33 @@ int parsefile(char *template, FILE *out) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
case AUTOESCAPE_CHAR:
|
||||||
|
for (++i; data->data[i] != ESCAPE_CHAR &&
|
||||||
|
i < data->len;
|
||||||
|
++i) {
|
||||||
|
switch (data->data[i]) {
|
||||||
|
case '&':
|
||||||
|
fputs("&", out);
|
||||||
|
break;
|
||||||
|
case ';':
|
||||||
|
fputs(";", out);
|
||||||
|
case '<':
|
||||||
|
fputs("<", out);
|
||||||
|
break;
|
||||||
|
case '>':
|
||||||
|
fputs(">", out);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
fputc(data->data[i], out);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
fputc(expanded->data->data[i], out);
|
fputc(file->data->data[i], out);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
error4:
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
for (i = 0; i < expanded->vars->len; ++i) {
|
|
||||||
struct var var;
|
|
||||||
var = getvector(expanded->vars, struct var, i);
|
|
||||||
freestring(var.var);
|
|
||||||
freestring(var.value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
freevector(expanded->vars);
|
|
||||||
error3:
|
|
||||||
freestring(expanded->data);
|
|
||||||
error2:
|
|
||||||
free(expanded);
|
|
||||||
error1:
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int expandfile(struct expandfile *ret, char *filename, int level) {
|
static int expandfile(struct expandfile *ret, char *filename, int level) {
|
||||||
@@ -120,7 +145,7 @@ static int expandfile(struct expandfile *ret, char *filename, int level) {
|
|||||||
if (appendchar(ret->data, ESCAPE_CHAR))
|
if (appendchar(ret->data, ESCAPE_CHAR))
|
||||||
goto error;
|
goto error;
|
||||||
break;
|
break;
|
||||||
case VAR_CHAR:
|
case VAR_CHAR: case AUTOESCAPE_CHAR:
|
||||||
if (appendchar(ret->data, ESCAPE_CHAR))
|
if (appendchar(ret->data, ESCAPE_CHAR))
|
||||||
goto error;
|
goto error;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
|
|||||||
Reference in New Issue
Block a user