Commit 807eb5c5 authored by Nils Goroll's avatar Nils Goroll

initial scaffolding

parent 764587bd
...@@ -29,3 +29,5 @@ Makefile.in ...@@ -29,3 +29,5 @@ Makefile.in
/src/vcc_if.c /src/vcc_if.c
/src/vcc_if.h /src/vcc_if.h
/src/vmod_*rst /src/vmod_*rst
/src/parse_encoding.c
/src/parse_encoding.h
...@@ -10,7 +10,14 @@ libvmod_convert_la_SOURCES = \ ...@@ -10,7 +10,14 @@ libvmod_convert_la_SOURCES = \
nodist_libvmod_convert_la_SOURCES = \ nodist_libvmod_convert_la_SOURCES = \
vcc_if.c \ vcc_if.c \
vcc_if.h vcc_if.h \
parse_encoding.h \
parse_encoding.c
parse_encoding.h: parse_encoding.c
parse_encoding.c: gen_enum_parse.pl
$(srcdir)/gen_enum_parse.pl parse_encoding.c parse_encoding.h
vmod_convert.lo: vcc_if.c vcc_if.h vmod_convert.lo: vcc_if.c vcc_if.h
...@@ -28,6 +35,7 @@ $(top_srcdir)/src/tests/*.vtc: libvmod_convert.la ...@@ -28,6 +35,7 @@ $(top_srcdir)/src/tests/*.vtc: libvmod_convert.la
check: $(VMOD_TESTS) check: $(VMOD_TESTS)
EXTRA_DIST = \ EXTRA_DIST = \
gen_enum_parse.pl \
vmod_convert.vcc \ vmod_convert.vcc \
$(VMOD_TESTS) $(VMOD_TESTS)
...@@ -35,4 +43,6 @@ CLEANFILES = \ ...@@ -35,4 +43,6 @@ CLEANFILES = \
$(builddir)/vcc_if.c \ $(builddir)/vcc_if.c \
$(builddir)/vcc_if.h \ $(builddir)/vcc_if.h \
$(builddir)/vmod_convert.rst \ $(builddir)/vmod_convert.rst \
$(builddir)/vmod_convert.man.rst $(builddir)/vmod_convert.man.rst \
$(builddir)/parse_encoding.h \
$(builddir)/parse_encoding.c
#!/usr/bin/perl
use strict;
use warnings;
use Carp::Assert;
sub _OUT {
my $fd = shift;
print $fd @_;
}
sub parse_token_code_gen {
my $fd = shift;
my $prevpos = shift; # 0, 1 ...
my $prev = shift; # "G", "GE", ...
my $term = shift; # function(macro) name to check if a symbol is terminator
assert ((scalar(@_) % 2) == 0);
my %symbs = @_; # symbol => result, ...
my $pos = $prevpos + 1;
# label
if ($prevpos != -1) {
_OUT ($fd, ' _'.$prevpos.$prev.":\n");
}
my $nsymbs = scalar(keys %symbs);
assert ($nsymbs);
if ($nsymbs == 1) {
my ($m, $r) = %symbs;
my @cond;
# optimize for just this one string
my $i;
for ($i = $pos; $i < length($m); $i++) {
push @cond, '(m['.$i."] == '".substr($m, $i, 1)."')";
}
push @cond, '('.$term.'(m['.$i."]))";
_OUT ($fd, "\t//".$m."\n");
_OUT ($fd, "\t".'if ('.join(" && ", @cond).') {'."\n");
_OUT ($fd, "\t".' r = '.$r.";\n");
_OUT ($fd, "\t".' p = '.$i.";\n");
_OUT ($fd, "\t".' goto ok;'."\n");
_OUT ($fd, "\t"."}\n");
_OUT ($fd, "\t".'goto invalid;'."\n");
} else {
my @case;
my @tocall;
{
## terminating keys
foreach my $m (grep { (length($_) == $pos) } sort keys %symbs) {
my $r = delete $symbs{$m};
_OUT ($fd, "\t//".$m."\n");
_OUT ($fd, "\t".'if ('.$term.'(m['.$pos.'])) {'."\n");
_OUT ($fd, "\t".' r = '.$r.";\n");
_OUT ($fd, "\t".' p = '.$pos.";\n");
_OUT ($fd, "\t".' goto ok;'."\n");
_OUT ($fd, "\t"."}\n");
}
}
{
## non-terminating keys
my @keys = (sort keys %symbs);
# hash by this char
my %h;
foreach my $k (@keys) {
assert( length($k) > $pos );
push @{$h{substr($k, $pos, 1)}}, ($k);
}
foreach my $k (sort keys %h) {
my $la = '_'.$pos.$prev.$k;
my @me = @{$h{$k}};
push @case, ("case '".$k."':\tgoto ".$la.";\t// ".
join(", ",@me));
push @tocall, [$prev.$k, \@me];
}
}
push @case, ("default:\tgoto invalid;");
_OUT ($fd, "\t".'switch (m['.$pos."]) {\n\t");
_OUT ($fd, join("\n\t", @case)."\n");
_OUT ($fd, "\t}\n");
if (scalar(@tocall)) {
map {
parse_token_code_gen($fd, $pos, $_->[0],
$term,
(map { $_ => $symbs{$_}; }
@{$_->[1]}));
} @tocall;
}
}
}
my @vals = (qw(
IDENTITY
BASE64
HEX
HEXLC));
unless ($#ARGV == 1) {
printf(STDERR 'Usage: '.$0." <c-file> <h-file>\n");
exit 1;
}
my ($c_file, $h_file) = @ARGV;
open(my $c_out, '>', $c_file) || die('cannot open '.$c_file.': '.$!);
open(my $h_out, '>', $h_file) || die('cannot open '.$h_file.': '.$!);
_OUT($h_out, <<'EOF');
/* AUTO-GENERATED, DO NOT EDIT */
EOF
_OUT($h_out,
"enum encoding {\n\t_INVALID = 0,\n\t".
join(",\n\t", @vals)."\n};\n");
_OUT($h_out, <<'EOF');
enum encoding parse_encoding (const char *);
EOF
_OUT($c_out, <<EOF);
/* AUTO-GENERATED, DO NOT EDIT */
#include "$h_file"
#define term(c) ((c) == '\\0')
EOF
_OUT($c_out, <<'EOF');
enum encoding
parse_encoding (const char *m) {
int p;
enum encoding r;
EOF
parse_token_code_gen($c_out, -1, '', 'term',
map { ($_ => $_) } @vals);
_OUT($c_out, <<EOF);
ok:
return r;
invalid:
return _INVALID;
(void)p;
}
EOF
close($c_out) || die('error closing '.$c_file.': '.$!);
close($h_out) || die('error closing '.$h_file.': '.$!);
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include "cache/cache.h" #include "cache/cache.h"
#include "vcc_if.h" #include "vcc_if.h"
#include "parse_encoding.h"
int int
init_function(struct vmod_priv *priv, const struct VCL_conf *conf) init_function(struct vmod_priv *priv, const struct VCL_conf *conf)
...@@ -12,22 +13,48 @@ init_function(struct vmod_priv *priv, const struct VCL_conf *conf) ...@@ -12,22 +13,48 @@ init_function(struct vmod_priv *priv, const struct VCL_conf *conf)
return (0); return (0);
} }
VCL_STRING // XXX this or just return NULL ?
vmod_hello(const struct vrt_ctx *ctx, VCL_STRING name) static const struct vmod_priv const null_blob[1] =
{ {
char *p; {
unsigned u, v; .priv = NULL,
.len = 0,
u = WS_Reserve(ctx->ws, 0); /* Reserve some work space */ .free = NULL
p = ctx->ws->f; /* Front of workspace area */
v = snprintf(p, u, "Hello, %s", name);
v++;
if (v > u) {
/* No space, reset and leave */
WS_Release(ctx->ws, 0);
return (NULL);
} }
/* Update work space with what we've used */ };
WS_Release(ctx->ws, v);
return (p); /* Functions */
VCL_BLOB
vmod_decode(VRT_CTX, VCL_ENUM decs, const char *p, ...) {
enum encoding dec = parse_encoding(decs);
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
assert(dec != _INVALID);
return null_blob;
}
VCL_STRING
vmod_encode(VRT_CTX, VCL_ENUM encs, VCL_BLOB b) {
enum encoding enc = parse_encoding(encs);
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
assert(enc != _INVALID);
return "XXX";
}
VCL_STRING
vmod_transcode(VRT_CTX, VCL_ENUM decs, VCL_ENUM encs, const char *p, ...) {
enum encoding dec = parse_encoding(decs);
enum encoding enc = parse_encoding(encs);
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
assert(dec != _INVALID);
assert(enc != _INVALID);
return p;
}
VCL_BLOB
vmod_transcode_blob(VRT_CTX, VCL_ENUM decs, VCL_ENUM encs, VCL_BLOB b) {
enum encoding dec = parse_encoding(decs);
enum encoding enc = parse_encoding(encs);
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
assert(dec != _INVALID);
assert(enc != _INVALID);
return b;
} }
...@@ -4,24 +4,21 @@ ...@@ -4,24 +4,21 @@
# (vmodtool requires this format.) # (vmodtool requires this format.)
# #
$Module convert 3 Example VMOD $Module convert 3 Convert between different encodings and strings/blobs
DESCRIPTION DESCRIPTION
=========== ===========
This is the embedded documentation for the convert VMOD. It should XXX write doc
mention what the vmod is intended to do. XXX gen ENUMs
It can span multiple lines and is written in RST format.
You can even have links and lists in here:
* https://github.com/varnish/libvmod-convert/
* https://www.varnish-cache.org/
The init-function declared next does not have documentation.
$Init init_function $Init init_function
$Function STRING hello(STRING)
The different functions provided by the VMOD should also have their own $Function BLOB decode(ENUM { IDENTITY, BASE64, HEX}, STRING_LIST)
embedded documentation. This section is for the hello() function. XXX DOC
$Function STRING encode(ENUM { IDENTITY, BASE64, HEXLC}, BLOB)
XXX DOC
$Function STRING transcode(ENUM { IDENTITY, BASE64, HEX}, ENUM { IDENTITY, BASE64, HEXLC}, STRING_LIST)
XXX DOC
$Function BLOB transcode_blob(ENUM { IDENTITY, BASE64, HEX}, ENUM { IDENTITY, BASE64, HEXLC}, BLOB)
XXX DOC
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment