gluon-web: clean up parser
This commit is contained in:
parent
5a20f9794c
commit
3203970969
@ -19,6 +19,53 @@
|
|||||||
|
|
||||||
#include "template_lmo.h"
|
#include "template_lmo.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fnmatch.h>
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
|
|
||||||
|
struct lmo_entry {
|
||||||
|
uint32_t key_id;
|
||||||
|
uint32_t val_id;
|
||||||
|
uint32_t offset;
|
||||||
|
uint32_t length;
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
typedef struct lmo_entry lmo_entry_t;
|
||||||
|
|
||||||
|
|
||||||
|
struct lmo_archive {
|
||||||
|
int fd;
|
||||||
|
int length;
|
||||||
|
uint32_t size;
|
||||||
|
lmo_entry_t *index;
|
||||||
|
char *mmap;
|
||||||
|
char *end;
|
||||||
|
struct lmo_archive *next;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct lmo_archive lmo_archive_t;
|
||||||
|
|
||||||
|
|
||||||
|
struct lmo_catalog {
|
||||||
|
char lang[6];
|
||||||
|
struct lmo_archive *archives;
|
||||||
|
struct lmo_catalog *next;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct lmo_catalog lmo_catalog_t;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Hash function from http://www.azillionmonkeys.com/qed/hash.html
|
* Hash function from http://www.azillionmonkeys.com/qed/hash.html
|
||||||
* Copyright (C) 2004-2008 by Paul Hsieh
|
* Copyright (C) 2004-2008 by Paul Hsieh
|
||||||
|
@ -20,52 +20,7 @@
|
|||||||
#ifndef _TEMPLATE_LMO_H_
|
#ifndef _TEMPLATE_LMO_H_
|
||||||
#define _TEMPLATE_LMO_H_
|
#define _TEMPLATE_LMO_H_
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stddef.h>
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <sys/mman.h>
|
|
||||||
#include <arpa/inet.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <fnmatch.h>
|
|
||||||
#include <dirent.h>
|
|
||||||
#include <ctype.h>
|
|
||||||
#include <limits.h>
|
|
||||||
|
|
||||||
|
|
||||||
struct lmo_entry {
|
|
||||||
uint32_t key_id;
|
|
||||||
uint32_t val_id;
|
|
||||||
uint32_t offset;
|
|
||||||
uint32_t length;
|
|
||||||
} __attribute__((packed));
|
|
||||||
|
|
||||||
typedef struct lmo_entry lmo_entry_t;
|
|
||||||
|
|
||||||
|
|
||||||
struct lmo_archive {
|
|
||||||
int fd;
|
|
||||||
int length;
|
|
||||||
uint32_t size;
|
|
||||||
lmo_entry_t *index;
|
|
||||||
char *mmap;
|
|
||||||
char *end;
|
|
||||||
struct lmo_archive *next;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct lmo_archive lmo_archive_t;
|
|
||||||
|
|
||||||
|
|
||||||
struct lmo_catalog {
|
|
||||||
char lang[6];
|
|
||||||
struct lmo_archive *archives;
|
|
||||||
struct lmo_catalog *next;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct lmo_catalog lmo_catalog_t;
|
|
||||||
|
|
||||||
|
|
||||||
int lmo_load_catalog(const char *lang, const char *dir);
|
int lmo_load_catalog(const char *lang, const char *dir);
|
||||||
|
@ -21,6 +21,14 @@
|
|||||||
#include "template_utils.h"
|
#include "template_utils.h"
|
||||||
#include "template_lmo.h"
|
#include "template_lmo.h"
|
||||||
|
|
||||||
|
#include <lualib.h>
|
||||||
|
#include <lauxlib.h>
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
|
||||||
#define TEMPLATE_LUALIB_META "gluon.web.template.parser"
|
#define TEMPLATE_LUALIB_META "gluon.web.template.parser"
|
||||||
|
|
||||||
|
|
||||||
|
@ -21,20 +21,79 @@
|
|||||||
#include "template_utils.h"
|
#include "template_utils.h"
|
||||||
#include "template_lmo.h"
|
#include "template_lmo.h"
|
||||||
|
|
||||||
|
#include <lualib.h>
|
||||||
|
#include <lauxlib.h>
|
||||||
|
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
|
||||||
|
/* code types */
|
||||||
|
#define T_TYPE_INIT 0
|
||||||
|
#define T_TYPE_TEXT 1
|
||||||
|
#define T_TYPE_COMMENT 2
|
||||||
|
#define T_TYPE_EXPR 3
|
||||||
|
#define T_TYPE_INCLUDE 4
|
||||||
|
#define T_TYPE_I18N 5
|
||||||
|
#define T_TYPE_I18N_RAW 6
|
||||||
|
#define T_TYPE_CODE 7
|
||||||
|
#define T_TYPE_EOF 8
|
||||||
|
|
||||||
|
|
||||||
|
struct template_chunk {
|
||||||
|
const char *s;
|
||||||
|
const char *e;
|
||||||
|
int type;
|
||||||
|
int line;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* parser state */
|
||||||
|
struct template_parser {
|
||||||
|
int fd;
|
||||||
|
size_t size;
|
||||||
|
char *data;
|
||||||
|
char *off;
|
||||||
|
char *lua_chunk;
|
||||||
|
int line;
|
||||||
|
int in_expr;
|
||||||
|
bool strip_before;
|
||||||
|
bool strip_after;
|
||||||
|
struct template_chunk prv_chunk;
|
||||||
|
struct template_chunk cur_chunk;
|
||||||
|
const char *file;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/* leading and trailing code for different types */
|
/* leading and trailing code for different types */
|
||||||
static const char *const gen_code[9][2] = {
|
static const char *const gen_code[][2] = {
|
||||||
{NULL, NULL},
|
[T_TYPE_INIT] = {NULL, NULL},
|
||||||
{"write(\"", "\")"},
|
[T_TYPE_TEXT] = {"write(\"", "\")"},
|
||||||
{NULL, NULL},
|
[T_TYPE_COMMENT] = {NULL, NULL},
|
||||||
{"write(tostring(", " or \"\"))"},
|
[T_TYPE_EXPR] = {"write(tostring(", " or \"\"))"},
|
||||||
{"include(\"", "\")"},
|
[T_TYPE_INCLUDE] = {"include(\"", "\")"},
|
||||||
{"write(\"", "\")"},
|
[T_TYPE_I18N] = {"write(\"", "\")"},
|
||||||
{"write(\"", "\")"},
|
[T_TYPE_I18N_RAW] = {"write(\"", "\")"},
|
||||||
{NULL, " "},
|
[T_TYPE_CODE] = {NULL, " "},
|
||||||
{}
|
[T_TYPE_EOF] = {NULL, NULL},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static struct template_parser * template_init(struct template_parser *parser)
|
||||||
|
{
|
||||||
|
parser->off = parser->data;
|
||||||
|
parser->cur_chunk.type = T_TYPE_INIT;
|
||||||
|
parser->cur_chunk.s = parser->data;
|
||||||
|
parser->cur_chunk.e = parser->data;
|
||||||
|
|
||||||
|
return parser;
|
||||||
|
}
|
||||||
|
|
||||||
struct template_parser * template_open(const char *file)
|
struct template_parser * template_open(const char *file)
|
||||||
{
|
{
|
||||||
struct stat s;
|
struct stat s;
|
||||||
@ -56,44 +115,29 @@ struct template_parser * template_open(const char *file)
|
|||||||
parser->data = mmap(NULL, parser->size, PROT_READ, MAP_PRIVATE,
|
parser->data = mmap(NULL, parser->size, PROT_READ, MAP_PRIVATE,
|
||||||
parser->fd, 0);
|
parser->fd, 0);
|
||||||
|
|
||||||
if (parser->data != MAP_FAILED)
|
if (parser->data == MAP_FAILED)
|
||||||
{
|
goto err;
|
||||||
parser->off = parser->data;
|
|
||||||
parser->cur_chunk.type = T_TYPE_INIT;
|
|
||||||
parser->cur_chunk.s = parser->data;
|
|
||||||
parser->cur_chunk.e = parser->data;
|
|
||||||
|
|
||||||
return parser;
|
return template_init(parser);
|
||||||
}
|
|
||||||
|
|
||||||
err:
|
err:
|
||||||
template_close(parser);
|
template_close(parser);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct template_parser * template_string(const char *str, uint32_t len)
|
struct template_parser * template_string(const char *str, size_t len)
|
||||||
{
|
{
|
||||||
struct template_parser *parser;
|
struct template_parser *parser;
|
||||||
|
|
||||||
if (!str) {
|
|
||||||
errno = EINVAL;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(parser = calloc(1, sizeof(*parser))))
|
if (!(parser = calloc(1, sizeof(*parser))))
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
parser->fd = -1;
|
parser->fd = -1;
|
||||||
|
|
||||||
parser->size = len;
|
parser->size = len;
|
||||||
parser->data = (char*)str;
|
parser->data = (char *)str;
|
||||||
|
|
||||||
parser->off = parser->data;
|
return template_init(parser);
|
||||||
parser->cur_chunk.type = T_TYPE_INIT;
|
|
||||||
parser->cur_chunk.s = parser->data;
|
|
||||||
parser->cur_chunk.e = parser->data;
|
|
||||||
|
|
||||||
return parser;
|
|
||||||
|
|
||||||
err:
|
err:
|
||||||
template_close(parser);
|
template_close(parser);
|
||||||
@ -105,8 +149,7 @@ void template_close(struct template_parser *parser)
|
|||||||
if (!parser)
|
if (!parser)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (parser->gc != NULL)
|
free(parser->lua_chunk);
|
||||||
free(parser->gc);
|
|
||||||
|
|
||||||
/* if file is not set, we were parsing a string */
|
/* if file is not set, we were parsing a string */
|
||||||
if (parser->file) {
|
if (parser->file) {
|
||||||
@ -124,18 +167,14 @@ static void template_text(struct template_parser *parser, const char *e)
|
|||||||
{
|
{
|
||||||
const char *s = parser->off;
|
const char *s = parser->off;
|
||||||
|
|
||||||
if (s < (parser->data + parser->size))
|
if (s < (parser->data + parser->size)) {
|
||||||
{
|
if (parser->strip_after) {
|
||||||
if (parser->strip_after)
|
while ((s < e) && isspace(s[0]))
|
||||||
{
|
|
||||||
while ((s <= e) && isspace(*s))
|
|
||||||
s++;
|
s++;
|
||||||
}
|
}
|
||||||
|
|
||||||
parser->cur_chunk.type = T_TYPE_TEXT;
|
parser->cur_chunk.type = T_TYPE_TEXT;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
parser->cur_chunk.type = T_TYPE_EOF;
|
parser->cur_chunk.type = T_TYPE_EOF;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -148,57 +187,53 @@ static void template_code(struct template_parser *parser, const char *e)
|
|||||||
{
|
{
|
||||||
const char *s = parser->off;
|
const char *s = parser->off;
|
||||||
|
|
||||||
parser->strip_before = 0;
|
parser->strip_before = false;
|
||||||
parser->strip_after = 0;
|
parser->strip_after = false;
|
||||||
|
|
||||||
if (*s == '-')
|
if (s < e && s[0] == '-') {
|
||||||
{
|
parser->strip_before = true;
|
||||||
parser->strip_before = 1;
|
s++;
|
||||||
for (s++; (s <= e) && (*s == ' ' || *s == '\t'); s++);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*(e-1) == '-')
|
if (s < e && e[-1] == '-') {
|
||||||
{
|
parser->strip_after = true;
|
||||||
parser->strip_after = 1;
|
e--;
|
||||||
for (e--; (e >= s) && (*e == ' ' || *e == '\t'); e--);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (*s)
|
switch (*s) {
|
||||||
{
|
/* comment */
|
||||||
/* comment */
|
case '#':
|
||||||
case '#':
|
s++;
|
||||||
s++;
|
parser->cur_chunk.type = T_TYPE_COMMENT;
|
||||||
parser->cur_chunk.type = T_TYPE_COMMENT;
|
break;
|
||||||
break;
|
|
||||||
|
|
||||||
/* include */
|
/* include */
|
||||||
case '+':
|
case '+':
|
||||||
s++;
|
s++;
|
||||||
parser->cur_chunk.type = T_TYPE_INCLUDE;
|
parser->cur_chunk.type = T_TYPE_INCLUDE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* translate */
|
/* translate */
|
||||||
case ':':
|
case ':':
|
||||||
s++;
|
s++;
|
||||||
parser->cur_chunk.type = T_TYPE_I18N;
|
parser->cur_chunk.type = T_TYPE_I18N;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* translate raw */
|
/* translate raw */
|
||||||
case '_':
|
case '_':
|
||||||
s++;
|
s++;
|
||||||
parser->cur_chunk.type = T_TYPE_I18N_RAW;
|
parser->cur_chunk.type = T_TYPE_I18N_RAW;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* expr */
|
/* expr */
|
||||||
case '=':
|
case '=':
|
||||||
s++;
|
s++;
|
||||||
parser->cur_chunk.type = T_TYPE_EXPR;
|
parser->cur_chunk.type = T_TYPE_EXPR;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* code */
|
/* code */
|
||||||
default:
|
default:
|
||||||
parser->cur_chunk.type = T_TYPE_CODE;
|
parser->cur_chunk.type = T_TYPE_CODE;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
parser->cur_chunk.line = parser->line;
|
parser->cur_chunk.line = parser->line;
|
||||||
@ -206,142 +241,117 @@ static void template_code(struct template_parser *parser, const char *e)
|
|||||||
parser->cur_chunk.e = e;
|
parser->cur_chunk.e = e;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *
|
static struct template_buffer * template_format_chunk(struct template_parser *parser)
|
||||||
template_format_chunk(struct template_parser *parser, size_t *sz)
|
|
||||||
{
|
{
|
||||||
const char *s, *p;
|
const char *p;
|
||||||
const char *head, *tail;
|
const char *head, *tail;
|
||||||
struct template_chunk *c = &parser->prv_chunk;
|
struct template_chunk *c = &parser->prv_chunk;
|
||||||
struct template_buffer *buf;
|
|
||||||
|
|
||||||
*sz = 0;
|
if (parser->strip_before && c->type == T_TYPE_TEXT) {
|
||||||
s = parser->gc = NULL;
|
while ((c->e > c->s) && isspace(c->e[-1]))
|
||||||
|
|
||||||
if (parser->strip_before && c->type == T_TYPE_TEXT)
|
|
||||||
{
|
|
||||||
while ((c->e > c->s) && isspace(*(c->e - 1)))
|
|
||||||
c->e--;
|
c->e--;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* empty chunk */
|
/* empty chunk */
|
||||||
if (c->s == c->e)
|
if (c->type == T_TYPE_EOF)
|
||||||
{
|
return NULL;
|
||||||
if (c->type == T_TYPE_EOF)
|
|
||||||
{
|
|
||||||
*sz = 0;
|
|
||||||
s = NULL;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
*sz = 1;
|
|
||||||
s = " ";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* format chunk */
|
struct template_buffer *buf = buf_init(c->e - c->s);
|
||||||
else if ((buf = buf_init(c->e - c->s)) != NULL)
|
if (!buf)
|
||||||
{
|
return NULL;
|
||||||
|
|
||||||
|
if (c->e > c->s) {
|
||||||
if ((head = gen_code[c->type][0]) != NULL)
|
if ((head = gen_code[c->type][0]) != NULL)
|
||||||
buf_append(buf, head, strlen(head));
|
buf_append(buf, head, strlen(head));
|
||||||
|
|
||||||
switch (c->type)
|
switch (c->type) {
|
||||||
{
|
case T_TYPE_TEXT:
|
||||||
case T_TYPE_TEXT:
|
luastr_escape(buf, c->s, c->e - c->s, false);
|
||||||
luastr_escape(buf, c->s, c->e - c->s, 0);
|
break;
|
||||||
break;
|
|
||||||
|
|
||||||
case T_TYPE_EXPR:
|
case T_TYPE_EXPR:
|
||||||
buf_append(buf, c->s, c->e - c->s);
|
buf_append(buf, c->s, c->e - c->s);
|
||||||
for (p = c->s; p < c->e; p++)
|
for (p = c->s; p < c->e; p++)
|
||||||
parser->line += (*p == '\n');
|
parser->line += (*p == '\n');
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case T_TYPE_INCLUDE:
|
case T_TYPE_INCLUDE:
|
||||||
luastr_escape(buf, c->s, c->e - c->s, 0);
|
luastr_escape(buf, c->s, c->e - c->s, false);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case T_TYPE_I18N:
|
case T_TYPE_I18N:
|
||||||
luastr_translate(buf, c->s, c->e - c->s, 1);
|
luastr_translate(buf, c->s, c->e - c->s, true);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case T_TYPE_I18N_RAW:
|
case T_TYPE_I18N_RAW:
|
||||||
luastr_translate(buf, c->s, c->e - c->s, 0);
|
luastr_translate(buf, c->s, c->e - c->s, false);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case T_TYPE_CODE:
|
case T_TYPE_CODE:
|
||||||
buf_append(buf, c->s, c->e - c->s);
|
buf_append(buf, c->s, c->e - c->s);
|
||||||
for (p = c->s; p < c->e; p++)
|
for (p = c->s; p < c->e; p++)
|
||||||
parser->line += (*p == '\n');
|
parser->line += (*p == '\n');
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((tail = gen_code[c->type][1]) != NULL)
|
if ((tail = gen_code[c->type][1]) != NULL)
|
||||||
buf_append(buf, tail, strlen(tail));
|
buf_append(buf, tail, strlen(tail));
|
||||||
|
|
||||||
*sz = buf_length(buf);
|
|
||||||
s = parser->gc = buf_destroy(buf);
|
|
||||||
|
|
||||||
if (!*sz)
|
|
||||||
{
|
|
||||||
*sz = 1;
|
|
||||||
s = " ";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return s;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *template_reader(lua_State *L __attribute__((unused)), void *ud, size_t *sz)
|
const char * template_reader(lua_State *L __attribute__((unused)), void *ud, size_t *sz)
|
||||||
{
|
{
|
||||||
struct template_parser *parser = ud;
|
struct template_parser *parser = ud;
|
||||||
int rem = parser->size - (parser->off - parser->data);
|
|
||||||
char *tag;
|
|
||||||
|
|
||||||
parser->prv_chunk = parser->cur_chunk;
|
/* free previous chunk */
|
||||||
|
free(parser->lua_chunk);
|
||||||
|
parser->lua_chunk = NULL;
|
||||||
|
|
||||||
/* free previous string */
|
while (true) {
|
||||||
if (parser->gc)
|
int rem = parser->size - (parser->off - parser->data);
|
||||||
{
|
char *tag;
|
||||||
free(parser->gc);
|
|
||||||
parser->gc = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* before tag */
|
parser->prv_chunk = parser->cur_chunk;
|
||||||
if (!parser->in_expr)
|
|
||||||
{
|
/* before tag */
|
||||||
if ((tag = memmem(parser->off, rem, "<%", 2)) != NULL)
|
if (!parser->in_expr) {
|
||||||
{
|
if ((tag = memmem(parser->off, rem, "<%", 2)) != NULL) {
|
||||||
template_text(parser, tag);
|
template_text(parser, tag);
|
||||||
parser->off = tag + 2;
|
parser->off = tag + 2;
|
||||||
parser->in_expr = 1;
|
parser->in_expr = 1;
|
||||||
|
} else {
|
||||||
|
template_text(parser, parser->data + parser->size);
|
||||||
|
parser->off = parser->data + parser->size;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
/* inside tag */
|
||||||
template_text(parser, parser->data + parser->size);
|
else {
|
||||||
parser->off = parser->data + parser->size;
|
if ((tag = memmem(parser->off, rem, "%>", 2)) != NULL) {
|
||||||
|
template_code(parser, tag);
|
||||||
|
parser->off = tag + 2;
|
||||||
|
parser->in_expr = 0;
|
||||||
|
} else {
|
||||||
|
/* unexpected EOF */
|
||||||
|
template_code(parser, parser->data + parser->size);
|
||||||
|
|
||||||
|
*sz = 1;
|
||||||
|
return "\033";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct template_buffer *buf = template_format_chunk(parser);
|
||||||
|
if (!buf)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
*sz = buf_length(buf);
|
||||||
|
if (*sz) {
|
||||||
|
parser->lua_chunk = buf_destroy(buf);
|
||||||
|
return parser->lua_chunk;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* inside tag */
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if ((tag = memmem(parser->off, rem, "%>", 2)) != NULL)
|
|
||||||
{
|
|
||||||
template_code(parser, tag);
|
|
||||||
parser->off = tag + 2;
|
|
||||||
parser->in_expr = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* unexpected EOF */
|
|
||||||
template_code(parser, parser->data + parser->size);
|
|
||||||
|
|
||||||
*sz = 1;
|
|
||||||
return "\033";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return template_format_chunk(parser, sz);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int template_error(lua_State *L, struct template_parser *parser)
|
int template_error(lua_State *L, struct template_parser *parser)
|
||||||
@ -353,33 +363,30 @@ int template_error(lua_State *L, struct template_parser *parser)
|
|||||||
int line = 0;
|
int line = 0;
|
||||||
int chunkline = 0;
|
int chunkline = 0;
|
||||||
|
|
||||||
if ((ptr = memmem(err, strlen(err), "]:", 2)) != NULL)
|
if ((ptr = memmem(err, strlen(err), "]:", 2)) != NULL) {
|
||||||
{
|
|
||||||
chunkline = atoi(ptr + 2) - parser->prv_chunk.line;
|
chunkline = atoi(ptr + 2) - parser->prv_chunk.line;
|
||||||
|
|
||||||
while (*ptr)
|
while (*ptr) {
|
||||||
{
|
if (*ptr++ == ' ') {
|
||||||
if (*ptr++ == ' ')
|
|
||||||
{
|
|
||||||
err = ptr;
|
err = ptr;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (memmem(err, strlen(err), "'char(27)'", 10) != NULL)
|
if (memmem(err, strlen(err), "'char(27)'", 10) != NULL) {
|
||||||
{
|
|
||||||
off = parser->data + parser->size;
|
off = parser->data + parser->size;
|
||||||
err = "'%>' expected before end of file";
|
err = "'%>' expected before end of file";
|
||||||
chunkline = 0;
|
chunkline = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (ptr = parser->data; ptr < off; ptr++)
|
for (ptr = parser->data; ptr < off; ptr++) {
|
||||||
if (*ptr == '\n')
|
if (*ptr == '\n')
|
||||||
line++;
|
line++;
|
||||||
|
}
|
||||||
|
|
||||||
snprintf(msg, sizeof(msg), "Syntax error in %s:%d: %s",
|
snprintf(msg, sizeof(msg), "Syntax error in %s:%d: %s",
|
||||||
parser->file ? parser->file : "[string]", line + chunkline, err ? err : "(unknown error)");
|
parser->file ?: "[string]", line + chunkline, err ?: "(unknown error)");
|
||||||
|
|
||||||
lua_pushnil(L);
|
lua_pushnil(L);
|
||||||
lua_pushinteger(L, line + chunkline);
|
lua_pushinteger(L, line + chunkline);
|
||||||
|
@ -20,59 +20,14 @@
|
|||||||
#ifndef _TEMPLATE_PARSER_H_
|
#ifndef _TEMPLATE_PARSER_H_
|
||||||
#define _TEMPLATE_PARSER_H_
|
#define _TEMPLATE_PARSER_H_
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <sys/mman.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <ctype.h>
|
|
||||||
#include <errno.h>
|
|
||||||
|
|
||||||
#include <lua.h>
|
#include <lua.h>
|
||||||
#include <lualib.h>
|
|
||||||
#include <lauxlib.h>
|
|
||||||
|
|
||||||
|
|
||||||
/* code types */
|
struct template_parser;
|
||||||
#define T_TYPE_INIT 0
|
|
||||||
#define T_TYPE_TEXT 1
|
|
||||||
#define T_TYPE_COMMENT 2
|
|
||||||
#define T_TYPE_EXPR 3
|
|
||||||
#define T_TYPE_INCLUDE 4
|
|
||||||
#define T_TYPE_I18N 5
|
|
||||||
#define T_TYPE_I18N_RAW 6
|
|
||||||
#define T_TYPE_CODE 7
|
|
||||||
#define T_TYPE_EOF 8
|
|
||||||
|
|
||||||
|
|
||||||
struct template_chunk {
|
|
||||||
const char *s;
|
|
||||||
const char *e;
|
|
||||||
int type;
|
|
||||||
int line;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* parser state */
|
|
||||||
struct template_parser {
|
|
||||||
int fd;
|
|
||||||
uint32_t size;
|
|
||||||
char *data;
|
|
||||||
char *off;
|
|
||||||
char *gc;
|
|
||||||
int line;
|
|
||||||
int in_expr;
|
|
||||||
int strip_before;
|
|
||||||
int strip_after;
|
|
||||||
struct template_chunk prv_chunk;
|
|
||||||
struct template_chunk cur_chunk;
|
|
||||||
const char *file;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct template_parser * template_open(const char *file);
|
struct template_parser * template_open(const char *file);
|
||||||
struct template_parser * template_string(const char *str, uint32_t len);
|
struct template_parser * template_string(const char *str, size_t len);
|
||||||
void template_close(struct template_parser *parser);
|
void template_close(struct template_parser *parser);
|
||||||
|
|
||||||
const char *template_reader(lua_State *L, void *ud, size_t *sz);
|
const char *template_reader(lua_State *L, void *ud, size_t *sz);
|
||||||
|
@ -27,19 +27,15 @@
|
|||||||
/* initialize a buffer object */
|
/* initialize a buffer object */
|
||||||
struct template_buffer * buf_init(size_t size)
|
struct template_buffer * buf_init(size_t size)
|
||||||
{
|
{
|
||||||
if (size < 1024)
|
|
||||||
size = 1024;
|
|
||||||
|
|
||||||
struct template_buffer *buf = malloc(sizeof(*buf));
|
struct template_buffer *buf = malloc(sizeof(*buf));
|
||||||
|
|
||||||
if (buf != NULL) {
|
if (buf != NULL) {
|
||||||
buf->size = size;
|
buf->size = size;
|
||||||
buf->data = malloc(buf->size);
|
buf->data = malloc(buf->size);
|
||||||
|
buf->dptr = buf->data;
|
||||||
|
|
||||||
if (buf->data != NULL) {
|
if (buf->data != NULL || size == 0)
|
||||||
buf->dptr = buf->data;
|
|
||||||
return buf;
|
return buf;
|
||||||
}
|
|
||||||
|
|
||||||
free(buf);
|
free(buf);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user