Overview
| Comment: | more boilerplate, add template framework |
|---|---|
| Downloads: | Tarball | ZIP archive | SQL archive |
| Timelines: | family | ancestors | descendants | both | trunk |
| Files: | files | file ages | folders |
| SHA3-256: |
6f17de476745e01bc24c082213de5656 |
| User & Date: | lexi on 2020-12-14 14:40:34 |
| Other Links: | manifest | tags |
Context
|
2020-12-16
| ||
| 08:46 | iterating check-in: 59e1d7d56a user: lexi tags: trunk | |
|
2020-12-14
| ||
| 14:40 | more boilerplate, add template framework check-in: 6f17de4767 user: lexi tags: trunk | |
|
2020-12-10
| ||
| 05:28 | initial commit check-in: e18c9de34d user: lexi tags: trunk | |
Changes
Added cmdparse.t version [8abc7a6fc7].
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
return function(tbl) local options = terralib.types.newstruct('options') do local flags = '' for _,d in pairs(tbl) do flags = flags .. d[1] end local helpstr = 'usage: parsav [-' .. flags .. '] [<arg>...]\n' options.entries = { {field = 'arglist', type = lib.mem.ptr(rawstring)} } local shortcases, longcases, init = {}, {}, {} local self = symbol(&options) local arg = symbol(rawstring) local skip = label() for o,desc in pairs(tbl) do options.entries[#options.entries + 1] = { field = o, type = bool } helpstr = helpstr .. string.format(' -%s --%s: %s\n', desc[1], o, desc[2]) end for o,desc in pairs(tbl) do local flag = desc[1] init[#init + 1] = quote [self].[o] = false end shortcases[#shortcases + 1] = quote case [int8]([string.byte(flag)]) then [self].[o] = true end end longcases[#longcases + 1] = quote if lib.str.cmp([arg]+2, o) == 0 then [self].[o] = true goto [skip] end end end options.methods.parse = terra([self], argc: int, argv: &rawstring) [init] var parseopts = true self.arglist = lib.mem.heapa(rawstring, argc) var finalargc = 0 for i=0,argc do var [arg] = argv[i] if arg[0] == ('-')[0] and parseopts then if arg[1] == ('-')[0] then -- long option if arg[2] == 0 then -- last option parseopts = false else [longcases] end else -- short options var j = 1 while arg[j] ~= 0 do switch arg[j] do [shortcases] end j = j + 1 end end else self.arglist.ptr[finalargc] = arg finalargc = finalargc + 1 end ::[skip]:: end if finalargc == 0 then self.arglist:free() else self.arglist:resize(finalargc) end end options.helptxt = helpstr end return options end |
Modified common.lua from [9dc63595c4] to [3d397d42e6].
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
..
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
|
if val then return os.execute(cmd) else
local fd = io.popen(cmd,'r')
local t = fd:read('*a')
return chomp(t), fd:close()
end
end
local function dump(v,pfx)
pfx = pfx or ''
local np = pfx .. ' '
if type(v) == 'string' then
return string.format('%q', v)
elseif type(v) == 'table' then
local str = ''
for k,v in pairs(v) do
str = str .. string.format('%s[%s] = %s\n', np, dump(k,np), dump(v,np))
end
return '{\n' .. str .. pfx .. '}\n'
else
return string.format('%s', v)
end
end
local ping = function(path)
................................................................................
s = ({
yes = true, ['true'] = true, on = true, ['1'] = true;
no = false, ['false'] = false, off = false, ['0'] = false;
})[string.lower(s)]
if not s then return false end
return true
end
return {
exec = exec;
dump = dump;
ping = ping;
chomp = chomp;
map = map;
tobool = tobool;
append = function(a,b)
for _, v in pairs(b) do a[#a+1] = v end
end;
has = function(haystack,needle,eq)
eq = eq or function(a,b) return a == b end
for k,v in pairs(haystack) do
if eq(needle,v) then return k end
end
end;
parseargs = function(a)
local raw = false
local opts, args = {}, {}
for i,v in ipairs(a) do
if v == '--' then
raw = true
|
|
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
..
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
|
if val then return os.execute(cmd) else
local fd = io.popen(cmd,'r')
local t = fd:read('*a')
return chomp(t), fd:close()
end
end
local function dump(v,pfx,cyc)
pfx = pfx or ''
cyc = cyc or {}
local np = pfx .. ' '
if type(v) == 'table' then
if cyc[v] then return '<...>' else cyc[v] = true end
end
if type(v) == 'string' then
return string.format('%q', v)
elseif type(v) == 'table' then
local str = ''
for k,v in pairs(v) do
local tkey, tval = dump(k,np,cyc), dump(v,np,cyc)
str = str .. string.format('%s[%s] = %s\n', np, tkey,tval)
end
return '{\n' .. str .. pfx .. '}\n'
else
return string.format('%s', v)
end
end
local ping = function(path)
................................................................................
s = ({
yes = true, ['true'] = true, on = true, ['1'] = true;
no = false, ['false'] = false, off = false, ['0'] = false;
})[string.lower(s)]
if not s then return false end
return true
end
if ping '/dev/urandom' then
local r = io.open('/dev/urandom')
local ent = r:read(8) r:close()
local seed = 1 for i = 1, 8 do
seed = seed * string.byte(string.sub(ent,i,i))
end
math.randomseed(seed)
else math.randomseed(os.time()) end
return {
exec = exec;
dump = dump;
ping = ping;
chomp = chomp;
map = map;
tobool = tobool;
rndstr = function(len)
local s = ''
for i=1,len do
local ofs = math.random(0,10 + 26)
if ofs >= 10 then ofs = 0x60 + (ofs - 10)
else ofs = 0x30 + ofs end
s = s .. string.char(ofs)
end
return s
end;
append = function(a,b)
for _, v in pairs(b) do a[#a+1] = v end
end;
has = function(haystack,needle,eq)
eq = eq or function(a,b) return a == b end
for k,v in pairs(haystack) do
if eq(needle,v) then return k end
end
end;
ingest = function(f)
local h = io.open(f, 'r')
if h == nil then return nil end
local txt = f:read('*a') f:close()
return chomp(txt)
end;
parseargs = function(a)
local raw = false
local opts, args = {}, {}
for i,v in ipairs(a) do
if v == '--' then
raw = true
|
Modified config.lua from [f14c1e8df4] to [85408f7c8a].
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 .. 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 ... 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 |
local u = dofile('common.lua')
local default = function(var,def)
local v = os.getenv(var)
if v then return v else return def end
end
local posixes = {
linux = true; osx = true;
android = true; haiku = true;
}
local conf = {
pkg = {};
os = default('parsav_target_os', 'linux');
dist = default('parsav_dist', os.getenv('NIX_PATH') and 'nixos');
tgttrip = default('parsav_arch_triple'); -- target triple, used in xcomp
tgtcpu = default('parsav_arch_cpu'); -- target cpu, used in xcomp
tgthf = u.tobool(default('parsav_arch_armhf',true));
}
conf.posix = posixes[conf.os]
conf.exe = u.tobool(default('parsav_link',not conf.tgttrip)); -- turn off for partial builds
local fallback = dofile('pkgdata.lua')
local libfind do local mkf = function(p)
return function(l) return string.format(p,l) end
end
local unx = function(p)
return function(l)
if string.sub(l,1,3) == 'lib'
................................................................................
then return string.format('%s.%s',l,p)
else return string.format('lib%s.%s',l,p)
end
end
end
libfind = {
linux = {
static = unx 'a';
dynamic = unx 'so';
};
osx = { dynamic = mkf '%s.dylib'; };
win = { dynamic = mkf '%s.dll'; };
}
end
local pkg = function(name)
local fbo = fallback[name] and fallback[name].osvars
and fallback[name].osvars[conf.os .. '_' .. conf.dist]
local fbv = fallback[name] and fallback[name].vars
local pkgenv = function(e)
return os.getenv(string.format('parsav_pkg_%s_%s',name,e))
end
name = pkgenv('override') or name
local nul = function() end
local pkc, pkv = nul, nul
local cnfvar = function(v,e)
local eval = function(e)
if type(e) == 'function'
then return e(conf)
else return e
end
end
return pkgenv(v) or pkv(e or v) or (fbo and eval(fbo[v])) or (fbv and eval(fbv[v]))
end
if conf.posix then
pkc = function(...) return u.exec { 'pkg-config'; name; ... } end
local pkcv = function(...) return u.exec({ 'pkg-config'; name; ... }, true) end
if pkcv('--exists') == 0 then
pkv = function(v)
return pkc('--variable', v)
end
else pkc = nul end
else
print '(warn) configuring on non-POSIX OS, all relevant paths must be specified manually in environment variables or build will fail!'
end
local locdep = u.ping('./lib/' .. name)
local prefix
if locdep then
prefix = './lib/' .. name
end
prefix = prefix or cnfvar('prefix')
local libdir = cnfvar('libdir')
if not libdir then
if locdep
then libdir = prefix .. (cnfvar('builddir') or cnfvar('libbuilddir')) or ''
else libdir = prefix .. '/lib'
end
end
local incdir = cnfvar('incdir','includedir') or (prefix .. '/include')
local libstr = pkc '--libs-only-l' -- (--static is not reliable)
local libs = fallback[name] and fallback[name].libs or {}
local linkstatic = locdep
if (not locdep) and libstr then
libs = {}
for m in string.gmatch(libstr, '-l(%g+)') do
libs[#libs + 1] = m
end
else
................................................................................
local ldf = {}
for _,v in pairs(me.statlibs) do
local fl = libdir .. '/' .. v
if u.ping(fl) then ldf[#ldf+1] = fl end
end
me.linkargs = ldf
else
local arg = name
if string.sub(arg,1,3) == 'lib' then arg = string.sub(arg,4) end
local linkline = libstr or string.format('-l%s', arg)
me.linkargs = {
string.format('-L%s', me.libdir);
}
for m in string.gmatch(linkline, '(%g+)') do
me.linkargs[#me.linkargs+1] = m
end
-- siiiiigh
for _,l in pairs(libs) do
local sw = string.format('-l%s', l)
local found = false
for _,a in pairs(me.linkargs) do
if a == sw then found = true break end
end
if not found then
me.linkargs[#me.linkargs+1] = sw
end
end
end
end
pkg('mbedtls')
pkg('libhttp')
pkg('json-c')
return conf
|
> > > > > > > | | > > > > > > | > > > > > > > > > > > > > > > > > | > > > > > > > > > > > > > > > > > > > > > < < | < | | | | > > > < > > > > | > > > > | | | > | | | > > | | < < | < | < > | > | | | > | > | | > > |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 .. 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 ... 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 |
local u = dofile('common.lua')
local default = function(var,def)
local v = os.getenv(var)
if v then return v else return def end
end
local function coalesce(x,...)
if x ~= nil then return x else
if select('#',...) == 0 then return nil end
return coalesce(...)
end
end
local posixes = {
linux = true; osx = true;
android = true; haiku = true;
}
local default_os = 'linux'
local conf = {
pkg = {};
dist = default('parsav_dist', coalesce(
os.getenv('NIX_PATH') and 'nixos',
os.getenv('NIX_STORE') and 'nixos',
''));
tgttrip = default('parsav_arch_triple'); -- target triple, used in xcomp
tgtcpu = default('parsav_arch_cpu'); -- target cpu, used in xcomp
tgthf = u.tobool(default('parsav_arch_armhf',true));
build = {
id = u.rndstr(6);
release = u.ingest('release');
when = os.date();
};
feat = {};
}
if u.ping '.fslckout' or u.ping '_FOSSIL_' then
if u.ping '_FOSSIL_' then default_os = 'windows' end
conf.build.branch = u.exec { 'fossil', 'branch', 'current' }
conf.build.checkout = (u.exec { 'fossil', 'sql',
[[select value from localdb.vvar where name = 'checkout-hash']]
}):gsub("^'(.*)'$", '%1')
end
conf.os = default('parsav_host_os', default_os);
conf.tgtos = default('parsav_target_os', default_os);
conf.posix = posixes[conf.os]
conf.exe = u.tobool(default('parsav_link',not conf.tgttrip)); -- turn off for partial builds
conf.build.origin = coalesce(
os.getenv('parsav_builder'),
string.format('%s@%s', coalesce (
os.getenv('USER'),
u.exec{'whoami'}
), u.exec{'hostname'}) -- whoami and hostname are present on both windows & unix
)
if conf.build.release then
local v = conf.build.release
conf.build.str = string.format('release %s', conf.build.release)
else
conf.build.str = string.format('build %s-%s', conf.build.id, conf.build.origin)
if conf.build.branch then
conf.build.str = conf.build.str .. string.format(':%s(%s)',
conf.build.branch, string.sub(conf.build.checkout,1,10))
end
end
if conf.tgtos == 'linux' then
conf.feat.randomizer = default('parsav_feat_randomizer', 'kern')
else
conf.feat.randomizer = default('parsav_feat_randomizer', 'libc')
end
local choplib = function(l)
if string.sub(l,1,3) == 'lib' then return string.sub(l,4) end
return l
end
local fallback = dofile('pkgdata.lua')
local libfind do local mkf = function(p)
return function(l) return string.format(p,l) end
end
local unx = function(p)
return function(l)
if string.sub(l,1,3) == 'lib'
................................................................................
then return string.format('%s.%s',l,p)
else return string.format('lib%s.%s',l,p)
end
end
end
libfind = {
linux = { static = unx 'a', dynamic = unx 'so'; };
osx = { dynamic = mkf '%s.dylib'; };
win = { dynamic = mkf '%s.dll'; };
}
end
local pkg = function(name)
local fbo = fallback[name] and fallback[name].osvars and coalesce(
fallback[name].osvars[conf.os .. '_' .. conf.dist],
fallback[name].osvars[conf.os]
)
local fbv = fallback[name] and fallback[name].vars
local fb = fallback[name]
local pkgenv = function(e)
return os.getenv(string.format('parsav_pkg_%s_%s',name,e))
end
local nul = function() end
local pkc, pkv = nul, nul
local locdep = false
local cnfvar = function(v,e)
local eval = function(e)
if type(e) == 'function'
then return e(conf)
else return e
end
end
return coalesce(
pkgenv(v),
pkv(e or v),
(fbo and eval(fbo[v])),
(fbv and eval(fbv[v])))
end
local name = cnfvar('override') or name
local pcname = coalesce(cnfvar('pcname'), name)
if conf.posix then
pkc = function(...) if locdep then return nil end
return u.exec { 'pkg-config'; pcname; ... } end
local pkcv = function(...) return u.exec({ 'pkg-config'; pcname; ... }, true) end
if pkcv('--exists') == 0 then
pkv = function(v)
if locdep then return nil end
return pkc('--variable', v)
end
else pkc = nul end
else
print '(warn) configuring on non-POSIX OS, all relevant paths must be specified manually in environment variables or build will fail!'
end
locdep = u.ping('./lib/' .. name)
local incdir, libdir, prefix
if locdep then
prefix = './lib/' .. name
libdir = prefix .. coalesce(cnfvar('libbuilddir'),cnfvar('builddir'),'')
incdir = prefix .. coalesce(cnfvar('srcincdir'),cnfvar('builddir'),'/include')
else
prefix = coalesce(cnfvar('prefix'), '/usr')
libdir = cnfvar('libdir')
incdir = cnfvar('incdir','includedir')
end
libdir = libdir or prefix .. '/lib'
incdir = incdir or prefix .. '/include'
local libstr = pkc '--libs-only-l' -- (--static is not reliable)
local libs = fb and fb.libs or {}
local linkstatic = locdep
if (not locdep) and libstr then
libs = {}
for m in string.gmatch(libstr, '-l(%g+)') do
libs[#libs + 1] = m
end
else
................................................................................
local ldf = {}
for _,v in pairs(me.statlibs) do
local fl = libdir .. '/' .. v
if u.ping(fl) then ldf[#ldf+1] = fl end
end
me.linkargs = ldf
else
local arg = choplib(name)
local linkline = libstr
if not linkline and #libs == 0 then
linkline = string.format('-l%s', arg)
elseif not linkline then linkline = '' end
me.linkargs = {
string.format('-L%s', me.libdir);
}
for m in string.gmatch(linkline, '(%g+)') do
me.linkargs[#me.linkargs+1] = m
end
-- siiiiigh
for _,l in pairs(libs) do
local sw = string.format('-l%s', choplib(l))
local found = false
for _,a in pairs(me.linkargs) do
if a == sw then found = true break end
end
if not found then
me.linkargs[#me.linkargs+1] = sw
end
end
end
end
pkg('mbedtls')
pkg('mongoose')
pkg('json-c')
pkg('libc')
pkg('libpq')
return conf
|
Added crypt.t version [340864c560].
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 |
-- vim: ft=terra local const = { keybits = 2048; sighash = lib.md.MBEDTLS_MD_SHA256; } local err = { rawcode = terra(code: int) if code < 0 then code = -code end return code and 0xFF80 end; toobig = -lib.pk.MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE; } const.maxpemsz = math.floor((const.keybits / 8)*6.4) + 128 -- idk why this formula works but it basically seems to local ctx = lib.pk.mbedtls_pk_context local m = { pemfile = uint8[const.maxpemsz]; } local callbacks = {} if config.feat.randomizer == 'kern' then local rnd = terralib.externfunction('getrandom', {&opaque, intptr, uint} -> ptrdiff); terra callbacks.randomize(ctx: &opaque, dest: &uint8, sz: intptr): int return rnd(dest, sz, 0) end elseif config.feat.randomizer == 'devfs' then terra callbacks.randomize(ctx: &opaque, dest: &uint8, sz: intptr): int var gen = lib.io.open("/dev/urandom",0) lib.io.read(gen, dest, sz) lib.io.close(gen) return sz end elseif config.feat.randomizer == 'libc' then local rnd = terralib.externfunction('rand', {} -> int); local srnd = terralib.externfunction('srand', uint -> int); local time = terralib.includec 'time.h' lib.init[#lib.init + 1] = quote srnd(time.time(nil)) end print '(warn) using libc soft-rand function for cryptographic purposes, this is very bad!' terra callbacks.randomize(ctx: &opaque, dest: &uint8, sz: intptr): int for i=0,sz do dest[i] = [uint8](rnd()) end return sz end end terra m.pem(pub: bool, key: &ctx, buf: &uint8): bool if pub then return lib.pk.mbedtls_pk_write_pubkey_pem(key, buf, const.maxpemsz) == 0 else return lib.pk.mbedtls_pk_write_key_pem(key, buf, const.maxpemsz) == 0 end end m.destroy = lib.dispatch { [ctx] = function(v) return `lib.pk.mbedtls_pk_free(&v) end; [false] = function(ptr) return `ptr:free() end; } terra m.genkp(): lib.pk.mbedtls_pk_context lib.dbg('generating new keypair') var pk: ctx lib.pk.mbedtls_pk_init(&pk) lib.pk.mbedtls_pk_setup(&pk, lib.pk.mbedtls_pk_info_from_type(lib.pk.MBEDTLS_PK_RSA)) var rsa = [&lib.rsa.mbedtls_rsa_context](pk.pk_ctx) lib.rsa.mbedtls_rsa_gen_key(rsa, callbacks.randomize, nil, const.keybits, 65537) return pk end terra m.loadpriv(buf: &uint8, len: intptr): ctx lib.dbg('parsing saved keypair') var pk: ctx lib.pk.mbedtls_pk_init(&pk) lib.pk.mbedtls_pk_parse_key(&pk, buf, len + 1, nil, 0) return pk end terra m.sign(pk: &ctx, txt: rawstring, len: intptr) lib.dbg('signing message') var osz: intptr = 0 var sig = lib.mem.heapa(int8, 2048) var hash: uint8[32] lib.dbg('(1/2) hashing message') if lib.md.mbedtls_md(lib.md.mbedtls_md_info_from_type(const.sighash), [&uint8](txt), len, hash) ~= 0 then lib.bail('could not hash message') end lib.dbg('(2/2) signing hash') var ret = lib.pk.mbedtls_pk_sign(pk, const.sighash, hash, 0, [&uint8](sig.ptr), &osz, callbacks.randomize, nil) if ret ~= 0 then lib.bail('could not sign message hash') else sig:resize(osz) end return sig end terra m.verify(pk: &ctx, txt: rawstring, len: intptr, sig: rawstring, siglen: intptr): {bool, uint8} lib.dbg('verifying signature') var osz: intptr = 0 var hash: uint8[64] -- there does not appear to be any way to extract the hash algorithm -- from the message, so we just have to try likely algorithms until -- we find one that fits or give up. a security level is attached -- to indicate our relative confidence in the hash; 0 == 'likely forgeable' var algs = array( -- common hashes {lib.md.MBEDTLS_MD_SHA256, 'sha256', 2}, {lib.md.MBEDTLS_MD_SHA512, 'sha512', 3}, {lib.md.MBEDTLS_MD_SHA1, 'sha1', 1}, -- uncommon hashes {lib.md.MBEDTLS_MD_SHA384, 'sha384', 2}, {lib.md.MBEDTLS_MD_SHA224, 'sha224', 2}, -- bad hashes {lib.md.MBEDTLS_MD_MD5, 'md5', 0}, {lib.md.MBEDTLS_MD_MD4, 'md4', 0}, {lib.md.MBEDTLS_MD_MD2, 'md2', 0} ) for i = 0, [algs.type.N] do var hk, aname, secl = algs[i] lib.dbg('(1/2) trying hash algorithm ',aname) if lib.md.mbedtls_md(lib.md.mbedtls_md_info_from_type(hk), [&uint8](txt), len, hash) ~= 0 then lib.bail('could not hash message') end lib.dbg('(2/2) verifying hash') if lib.pk.mbedtls_pk_verify(pk, hk, hash, 0, [&uint8](sig), siglen) == 0 then return true, secl end end lib.dbg('all hash algorithms failed') return false, 0 end return m |
Added http.t version [6d6c40fc94].
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 |
-- vim: ft=terra local m = {} local util = dofile('common.lua') struct m.header { key: rawstring value: rawstring } struct m.page { respcode: uint16 body: lib.mem.ptr(int8) headers: lib.mem.ptr(m.header) } local resps = { [200] = 'OK'; [201] = 'Created'; [301] = 'Moved Permanently'; [302] = 'Found'; [303] = 'See Other'; [307] = 'Temporary Redirect'; [404] = 'Not Found'; [401] = 'Unauthorized'; [403] = 'Forbidden'; [418] = 'I\'m a teapot'; [405] = 'Method Not Allowed'; [500] = 'Internal Server Error'; } local resptext = symbol(rawstring) local resplen = symbol(intptr) local respbranches = {} for k,v in pairs(resps) do local txt = string.format('%u %s\r\n',k,v) respbranches[#respbranches + 1] = quote case [uint16](k) then resptext = [txt] resplen = [#txt] end end end m.codestr = terra(code: uint16) var [resptext] var [resplen] switch code do [respbranches] end return resptext, resplen end m.page.methods = { free = terra(self: &m.page) self.body:free() self.headers:free() end; send = terra(self: &m.page, con: &lib.net.mg_connection) var code: rawstring var [resptext] var [resplen] switch self.respcode do [respbranches] end lib.net.mg_send(con, "HTTP/1.1 ", 9) lib.net.mg_send(con, resptext, resplen) for i = 0, self.headers.ct do var h = self.headers.ptr[i] lib.net.mg_send(con, h.key, lib.str.sz(h.key)) lib.net.mg_send(con, ": ", 2) lib.net.mg_send(con, h.value, lib.str.sz(h.value)) lib.net.mg_send(con, "\r\n", 2) end lib.net.mg_printf(con, 'Content-Length: %llu\r\n\r\n', self.body.ct) lib.net.mg_send(con,self.body.ptr,self.body.ct) end; } return m |
Modified makefile from [b49975ddb0] to [0f98e9b572].
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
..
52
53
54
55
56
57
58
59
60
61
62
63
64
65
|
terra $(dbg-flags) $< parsav.o: parsav.t config.lua pkgdata.lua env parsav_link=no terra $(dbg-flags) $< clean: rm parsav parsav.o dep: dep.mbedtls dep.libhttp dep.json-c dep.mbedtls: lib/mbedtls/library/libmbedtls.a \ lib/mbedtls/library/libmbedcrypto.a \ lib/mbedtls/library/libmbedx509.a dep.libhttp: lib/libhttp/lib/libhttp.a dep.json-c: lib/libhttp/json-c.a lib: mkdir $@ # parsav is designed to be fronted by a real web # server like nginx if SSL is to be used # caveat: libhttp is a mess. the docs are completely # full of shit. there is no lua support as far as i # can tell. lib/libhttp/lib/libhttp.a: lib/libhttp $(MAKE) -C $< lib/libhttp.a \ RM='rm -f' \ CC="$(CC) -Wno-unused-result" \ DFLAGS="-DNO_SSL -DNO_FILES -DNO_CGI -DUSE_STACK_SIZE=102400 -DUSE_IPV6" lib/json-c/Makefile: lib/json-c lib/json-c/CMakeLists.txt cd lib/json-c && cmake . lib/json-c/libjson-c.a: lib/json-c/Makefile $(MAKE) -C lib/json-c lib/mbedtls/library/%.a: lib/mbedtls $(MAKE) -C lib/mbedtls/library $*.a ifeq ($(dl), git) lib/libhttp: lib cd lib && git clone https://github.com/lammertb/libhttp.git lib/mbedtls: lib cd lib && git clone https://github.com/ARMmbed/mbedtls.git lib/json-c: lib cd lib && git clone https://github.com/json-c/json-c.git else lib/%: lib/%.tar.gz cd lib && tar zxf $*.tar.gz ................................................................................ dlfile = wget "$(1)" -O "$(2)" endif ifeq ($(dl), curl) dlfile = curl "$(1)" -o "$(2)" endif lib/libhttp.tar.gz: lib $(call dlfile,https://api.github.com/repos/lammertb/libhttp/tarball/master,$@) lib/mbedtls.tar.gz: lib $(call dlfile,https://api.github.com/repos/ARMmbed/mbedtls/tarball/master,$@) lib/json-c.tar.gz: lib $(call dlfile,https://api.github.com/repos/json-c/json-c/tarball/master,$@) endif |
>
>
>
>
|
|
|
|
|
|
|
|
|
|
|
>
>
|
|
|
|
|
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
..
58
59
60
61
62
63
64
65
66
67
68
69
70
71
|
terra $(dbg-flags) $< parsav.o: parsav.t config.lua pkgdata.lua env parsav_link=no terra $(dbg-flags) $< clean: rm parsav parsav.o install: parsav mkdir $(prefix)/bin cp $< $(prefix)/bin/ dep: dep.mbedtls dep.mongoose dep.json-c dep.mbedtls: lib/mbedtls/library/libmbedtls.a \ lib/mbedtls/library/libmbedcrypto.a \ lib/mbedtls/library/libmbedx509.a dep.mongoose: lib/mongoose/libmongoose.a dep.json-c: lib/json-c/libjson-c.a lib: mkdir $@ # parsav is designed to be fronted by a real web # server like nginx if SSL is to be used # generate a shim static library so mongoose cooperates # with the build apparatus lib/mongoose/libmongoose.a: lib/mongoose lib/mongoose/mongoose.c lib/mongoose/mongoose.h $(CC) -c $</mongoose.c -o lib/mongoose/mongoose.o \ -DMG_ENABLE_THREADS \ -DMG_ENABLE_IPV6 \ -DMG_ENABLE_HTTP_WEBDAV \ -DMG_ENABLE_HTTP_WEBSOCKET=0 ar rcs $@ lib/mongoose/*.o ranlib $@ lib/json-c/Makefile: lib/json-c lib/json-c/CMakeLists.txt cd lib/json-c && cmake . lib/json-c/libjson-c.a: lib/json-c/Makefile $(MAKE) -C lib/json-c lib/mbedtls/library/%.a: lib/mbedtls $(MAKE) -C lib/mbedtls/library $*.a ifeq ($(dl), git) lib/mongoose: lib cd lib && git clone https://github.com/cesanta/mongoose lib/mbedtls: lib cd lib && git clone https://github.com/ARMmbed/mbedtls.git lib/json-c: lib cd lib && git clone https://github.com/json-c/json-c.git else lib/%: lib/%.tar.gz cd lib && tar zxf $*.tar.gz ................................................................................ dlfile = wget "$(1)" -O "$(2)" endif ifeq ($(dl), curl) dlfile = curl "$(1)" -o "$(2)" endif lib/mongoose.tar.gz: lib $(call dlfile,https://api.github.com/repos/cesanta/mongoose/tarball/master,$@) lib/mbedtls.tar.gz: lib $(call dlfile,https://api.github.com/repos/ARMmbed/mbedtls/tarball/master,$@) lib/json-c.tar.gz: lib $(call dlfile,https://api.github.com/repos/json-c/json-c/tarball/master,$@) endif |
Modified parsav.t from [d2f35b212c] to [889180c92d].
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
..
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
|
-- vim: ft=terra
local util = dofile('common.lua')
local buildopts, buildargs = util.parseargs{...}
local config = dofile('config.lua')
local lib = {
loadlib = function(name,hdr)
local p = config.pkg[name]
-- for _,v in pairs(p.dylibs) do
-- terralib.linklibrary(p.libdir .. '/' .. v)
-- end
return terralib.includec(p.incdir .. '/' .. hdr)
end;
randomize = terralib.externfunction('getrandom', {&opaque, intptr, uint} -> ptrdiff);
}
lib.rsa = lib.loadlib('mbedtls','mbedtls/rsa.h')
lib.pk = lib.loadlib('mbedtls','mbedtls/pk.h')
local callbacks = {
randomize = terra(ctx: &opaque, dest: &uint8, sz: intptr): int
return lib.randomize(dest, sz, 0)
end;
}
terra entry(): int
var pk: lib.pk.mbedtls_pk_context
lib.pk.mbedtls_pk_init(&pk)
lib.pk.mbedtls_pk_setup(&pk, lib.pk.mbedtls_pk_info_from_type(lib.pk.MBEDTLS_PK_RSA))
var rsa = [&lib.rsa.mbedtls_rsa_context](pk.pk_ctx)
lib.rsa.mbedtls_rsa_gen_key(rsa, callbacks.randomize, nil, 2048, 65537)
return 0
end
local bflag = function(long,short)
if short and util.has(buildopts, short) then return true end
if long and util.has(buildopts, long) then return true end
return false
................................................................................
end
local emit = print
if bflag('quiet','q') then emit = function() end end
local out = config.exe and 'parsav' or 'parsav.o'
local linkargs = {}
for _,p in pairs(config.pkg) do util.append(linkargs, p.linkargs) end
emit('linking with args',util.dump(linkargs))
terralib.saveobj(out, {
main = entry
},
linkargs,
config.tgttrip and terralib.newtarget {
Triple = config.tgttrip;
CPU = config.tgtcpu;
FloatABIHard = config.tgthf;
} or nil)
|
<
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
<
<
<
>
>
|
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
<
<
<
<
<
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
...
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
|
-- vim: ft=terra
local util = dofile('common.lua')
local buildopts, buildargs = util.parseargs{...}
config = dofile('config.lua')
lib = {
init = {};
loadlib = function(name,hdr)
local p = config.pkg[name]
-- for _,v in pairs(p.dylibs) do
-- terralib.linklibrary(p.libdir .. '/' .. v)
-- end
return terralib.includec(p.incdir .. '/' .. hdr)
end;
dispatch = function(tbl)
return macro(function(v,...)
for ty,fn in pairs(tbl) do
if v.tree.type == ty then return fn(v,...) end
end
return (tbl[false])(v,...)
end)
end;
emit = function(...)
local code = {}
for i,v in ipairs{...} do
if type(v) == 'string' or type(v) == 'number' then
local str = tostring(v)
code[#code+1] = `lib.io.send(2, str, [#str])
elseif v.tree:is 'constant' then
local str = tostring(v:asvalue())
code[#code+1] = `lib.io.send(2, str, [#str])
else
code[#code+1] = quote var n = v in
lib.io.send(2, n, lib.str.sz(n)) end
end
end
code[#code+1] = `lib.io.send(2, '\n', 1)
return code
end;
proc = {
exit = terralib.externfunction('exit', int -> {});
getenv = terralib.externfunction('getenv', rawstring -> rawstring);
};
io = {
open = terralib.externfunction('open', {rawstring, int} -> int);
close = terralib.externfunction('close', {int} -> int);
send = terralib.externfunction('write', {int, rawstring, intptr} -> ptrdiff);
recv = terralib.externfunction('read', {int, rawstring, intptr} -> ptrdiff);
say = macro(function(msg) return `lib.io.send(2, msg, [#(msg:asvalue())]) end);
fmt = terralib.externfunction('printf',
terralib.types.funcpointer({rawstring},{int},true));
};
str = {
sz = terralib.externfunction('strlen', rawstring -> intptr);
cmp = terralib.externfunction('strcmp', {rawstring, rawstring} -> int);
cpy = terralib.externfunction('stpcpy',{rawstring, rawstring} -> rawstring);
ncpy = terralib.externfunction('stpncpy',{rawstring, rawstring, intptr} -> rawstring);
fmt = terralib.externfunction('asprintf',
terralib.types.funcpointer({&rawstring},{int},true));
};
mem = {
zero = macro(function(r)
return quote
for i = 0, [r.tree.type.N] do r[i] = 0 end
end
end);
heapa_raw = terralib.externfunction('malloc', intptr -> &opaque);
heapr_raw = terralib.externfunction('realloc', {&opaque, intptr} -> &opaque);
heapf = terralib.externfunction('free', &opaque -> {});
cpy = terralib.externfunction('mempcpy',{&opaque, &opaque, intptr} -> &opaque);
heapa = macro(function(ty, sz)
local p = lib.mem.ptr(ty:astype())
return `p {
ptr = [&ty:astype()](lib.mem.heapa_raw(sizeof(ty) * sz));
ct = sz;
}
end)
};
}
local noise = global(uint8,1)
local defrep = function(level,n,code)
return macro(function(...)
local q = lib.emit("\27["..code..";1m(parsav "..n..")\27[m ", ...)
return quote
if noise >= level then [q] end
end
end);
end
lib.dbg = defrep(3,'debug', '32')
lib.report = defrep(2,'info', '35')
lib.warn = defrep(1,'warn', '33')
lib.bail = macro(function(...)
local q = lib.emit("\27[31;1m(parsav fatal)\27[m ", ...)
return quote
[q]
lib.proc.exit(1)
end
end);
lib.mem.ptr = terralib.memoize(function(ty)
local t = terralib.types.newstruct(string.format('ptr<%s>', ty))
t.entries = {
{'ptr', &ty};
{'ct', intptr};
}
local recurse = false
if ty:isstruct() then
if ty.methods.free then recurse = true end
end
t.methods = {
free = terra(self: &t): bool
[recurse and quote
self.ptr:free()
end or {}]
if self.ct > 0 then
lib.mem.heapf(self.ptr)
self.ct = 0
return true
end
return false
end;
init = terra(self: &t, newct: intptr): bool
var nv = [&ty](lib.mem.heapa_raw(sizeof(ty) * newct))
if nv ~= nil then
self.ptr = nv
self.ct = newct
return true
else return false end
end;
resize = terra(self: &t, newct: intptr): bool
var nv: &ty
if self.ct > 0
then nv = [&ty](lib.mem.heapr_raw(self.ptr, sizeof(ty) * newct))
else nv = [&ty](lib.mem.heapa_raw(sizeof(ty) * newct))
end
if nv ~= nil then
self.ptr = nv
self.ct = newct
return true
else return false end
end;
}
return t
end)
lib.err = lib.loadlib('mbedtls','mbedtls/error.h')
lib.rsa = lib.loadlib('mbedtls','mbedtls/rsa.h')
lib.pk = lib.loadlib('mbedtls','mbedtls/pk.h')
lib.md = lib.loadlib('mbedtls','mbedtls/md.h')
lib.b64 = lib.loadlib('mbedtls','mbedtls/base64.h')
lib.net = lib.loadlib('mongoose','mongoose.h')
lib.pq = lib.loadlib('libpq','libpq-fe.h')
lib.crypt = terralib.loadfile('crypt.t')()
lib.http = terralib.loadfile('http.t')()
lib.tpl = terralib.loadfile('tpl.t')()
lib.string = terralib.loadfile('string.t')()
lib.store = terralib.loadfile('store.t')()
lib.cmdparse = terralib.loadfile('cmdparse.t')()
do local collate = function(path,f, ...)
return loadfile(path..'/'..f..'.lua')(path, ...)
end
data = {
view = collate('view','load');
} end
-- slightly silly -- because we're using plain lua to gather up
-- the template sources, they have to be actually turned into
-- templates in the terra code, so we "mutate" them here
for k,v in pairs(data.view) do
local t = lib.tpl.mk { body = v, id = 'view/'..k }
data.view[k] = t
end
local pemdump = macro(function(pub, kp)
local msg = (pub:asvalue() and ' * emitting public key\n') or ' * emitting private key\n'
return quote
var buf: lib.crypt.pemfile
lib.mem.zero(buf)
lib.crypt.pem(pub, &kp, buf)
lib.io.send(1, msg, [#msg])
lib.io.send(1, [rawstring](&buf), lib.str.sz([rawstring](&buf)))
lib.io.send(1, '\n', 1)
end
end)
local handle = {
http = terra(con: &lib.net.mg_connection, event: int, p: &opaque, ext: &opaque)
switch event do
case lib.net.MG_EV_HTTP_MSG then
lib.dbg('routing HTTP request')
var msg = [&lib.net.mg_http_message](p)
end
end
end;
}
do
local p = string.format('parsav: %s\nbuilt on %s\n', config.build.str, config.build.when)
terra version() lib.io.send(1, p, [#p]) end
end
terra noise_init()
var n = lib.proc.getenv('parsav_noise')
if n ~= nil then
if n[0] >= 0x30 and n[0] <= 0x39 and n[1] == 0 then
noise = n[0] - 0x30
return
end
end
noise = 1
end
local options = lib.cmdparse {
version = {'V', 'display information about the binary build and exit'};
quiet = {'q', 'do not print to standard out'};
help = {'h', 'display this list'}
}
terra entry(argc: int, argv: &rawstring): int
noise_init()
[lib.init]
var mode: options
mode:parse(argc,argv)
if mode.version then
version()
return 0
end
if mode.help then
lib.io.send(1, [options.helptxt], [#options.helptxt])
return 0
end
var bind = lib.proc.getenv('parsav_bind')
if bind == nil then bind = '[::]:10917' end
var nm: lib.net.mg_mgr
lib.net.mg_mgr_init(&nm)
var nmc = lib.net.mg_http_listen(&nm, bind, handle.http, nil)
while true do
lib.net.mg_mgr_poll(&nm,1000)
end
lib.net.mg_mgr_free(&nm)
return 0
end
local bflag = function(long,short)
if short and util.has(buildopts, short) then return true end
if long and util.has(buildopts, long) then return true end
return false
................................................................................
end
local emit = print
if bflag('quiet','q') then emit = function() end end
local out = config.exe and 'parsav' or 'parsav.o'
local linkargs = {}
if config.posix then
linkargs[#linkargs+1] = '-pthread'
end
for _,p in pairs(config.pkg) do util.append(linkargs, p.linkargs) end
emit('linking with args',util.dump(linkargs))
terralib.saveobj(out, {
main = entry
},
linkargs,
config.tgttrip and terralib.newtarget {
Triple = config.tgttrip;
CPU = config.tgtcpu;
FloatABIHard = config.tgthf;
} or nil)
|
Modified pkgdata.lua from [b4c0388029] to [8c50f1b4b0].
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
local util = dofile('common.lua')
local sthunk = function(...) local a = {...} return function() return util.exec(a) end end
return {
mbedtls = {
libs = {'mbedtls', 'mbedcrypto', 'mbedx509'};
osvars = {
linux_nixos = { -- lacks a *.pc on nixos systems
prefix = sthunk('nix', 'path-info', 'nixos.mbedtls');
}
};
vars = { builddir = '/library' };
};
libhttp = { vars = { builddir = '/lib' }; };
}
|
> | > > > > > > > > | > > > > > > > > > > > > > > |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
local util = dofile('common.lua')
local sthunk = function(...) local a = {...} return function() return util.exec(a) end end
return {
mbedtls = {
libs = {'mbedtls', 'mbedcrypto', 'mbedx509'};
osvars = {
linux_nixos = { -- lacks a *.pc on nixos systems
prefix = sthunk('nix', 'path-info', 'nixos.mbedtls');
}
};
vars = { builddir = '/library' };
};
mongoose = { vars = { builddir = '' } };
libpq = {
osvars = {
linux_nixos = {
prefix = sthunk('nix', 'path-info', 'nixos.postgresql.lib');
incdir = function()
local a = {'nix', 'path-info', 'nixos.postgresql'}
return (util.exec(a)) .. '/include';
end;
};
};
vars = {pcname = 'postgresql';}
};
libc = {
libs = {'dl'}; -- libc.so does not need explicit mention
osvars = {
linux_nixos = {
prefix = sthunk('nix', 'path-info', 'nixos.glibc');
override = 'glibc';
};
linux = { override = 'glibc'; };
}
};
}
|
Added store.t version [a0814e5c61].
> > > > > > > > > > > > > > > |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
-- vim: ft=terra local m = {} local backend = { pgsql = { }; } struct m.user { uid: rawstring nym: rawstring handle: rawstring localuser: bool } |
Added string.t version [a0d1de486b].
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
-- vim: ft=terra -- string.t: string classes local m = {} struct m.acc { buf: rawstring sz: intptr run: intptr space: intptr } local terra biggest(a: intptr, b: intptr) if a > b then return a else return b end end m.acc.methods = { init = terra(self: &m.acc, run: intptr) lib.dbg('initializing string accumulator') self.buf = [rawstring](lib.mem.heapa_raw(run)) self.run = run self.space = run self.sz = 0 end; free = terra(self: &m.acc) lib.dbg('freeing string accumulator') if self.buf ~= nil and self.space > 0 then lib.mem.heapf(self.buf) end end; crush = terra(self: &m.acc) lib.dbg('crushing string accumulator') self.buf = [rawstring](lib.mem.heapr_raw(self.buf, self.sz)) self.space = self.sz return self end; } m.acc.methods.finalize = terra(self: &m.acc) lib.dbg('finalizing string accumulator') self:crush() var pt: lib.mem.ptr(int8) pt.ptr = self.buf pt.ct = self.sz self.buf = nil self.sz = 0 return pt end; m.acc.methods.push = terra(self: &m.acc, str: rawstring, len: intptr) lib.dbg('pushing "',str,'" onto accumulator') if self.buf == nil then self:init(self.run) end if len == 0 then len = lib.str.sz(str) end if len >= self.space - self.sz then self.space = self.space + biggest(self.run,len + 1) self.buf = [rawstring](lib.mem.heapr_raw(self.buf, self.space)) end lib.mem.cpy(self.buf + self.sz, str, len) self.sz = self.sz + len self.buf[self.sz] = 0 return self end; m.acc.methods.ppush = terra(self: &m.acc, str: lib.mem.ptr(int8)) self:push(str.ptr, str.ct) return self end; m.acc.methods.merge = terra(self: &m.acc, str: lib.mem.ptr(int8)) self:push(str.ptr, str.ct) str:free() return self end; return m |
Added tpl.t version [ad44dd6129].
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 |
-- vim: ft=terra -- string template generator: -- returns a function that fills out a template -- with the strings given local util = dofile 'common.lua' local m = {} function m.mk(tplspec) local str if type(tplspec) == 'string' then str = tplspec tplspec = {} else str = tplspec.body end local tplchar_o = tplspec.sigil or '@' local tplchar = tplchar_o local magic = { ['%'] = true, ['$'] = true, ['^'] = true; ['.'] = true, ['*'] = true, ['+'] = true; ['-'] = true, ['?'] = true; } tplchar_o = string.gsub(tplchar_o,'%%','%%%%') tplchar = string.gsub(tplchar, '.', function(c) if magic[c] then return '%' .. c end end) local last = 1 local fields = {} local segs = {} local constlen = 0 -- strip out all irrelevant whitespace to tidy things up -- TODO: find way to exclude <pre> tags? str = str:gsub('[\n^]%s+','') str = str:gsub('%s+[\n$]','') str = str:gsub('\n','') for start, key, stop in string.gmatch(str,'()'..tplchar..'(%w+)()') do if string.sub(str,start-1,start-1) ~= '\\' then segs[#segs+1] = string.sub(str,last,start-1) fields[#segs] = key last = stop end end segs[#segs+1] = string.sub(str,last) for i, s in ipairs(segs) do segs[i] = string.gsub(s, '\\'..tplchar, tplchar_o) constlen = constlen + string.len(segs[i]) end local runningtally = symbol(intptr) local tallyup = {quote var [runningtally] = 1 + constlen end} local rec = terralib.types.newstruct(string.format('template<%s>',tplspec.id or '')) local symself = symbol(&rec) do local kfac = {} for afterseg,key in pairs(fields) do if not kfac[key] then rec.entries[#rec.entries + 1] = { field = key; type = rawstring; } end kfac[key] = (kfac[key] or 0) + 1 end for key, fac in pairs(kfac) do tallyup[#tallyup + 1] = quote [runningtally] = [runningtally] + lib.str.sz([symself].[key])*fac end end end local copiers = {} local senders = {} local symtxt = symbol(lib.mem.ptr(int8)) local cpypos = symbol(&opaque) local destcon = symbol(&lib.net.mg_connection) for idx, seg in ipairs(segs) do copiers[#copiers+1] = quote [cpypos] = lib.mem.cpy([cpypos], [&opaque]([seg]), [#seg]) end senders[#senders+1] = quote lib.net.mg_send([destcon], [seg], [#seg]) end if fields[idx] then copiers[#copiers+1] = quote [cpypos] = lib.mem.cpy([cpypos], [&opaque](symself.[fields[idx]]), lib.str.sz(symself.[fields[idx]])) end senders[#senders+1] = quote lib.net.mg_send([destcon], symself.[fields[idx]], lib.str.sz(symself.[fields[idx]])) end end end local tid = tplspec.id or '<anonymous>' rec.methods.tostr = terra([symself]) lib.dbg(['compiling template ' .. tid]) [tallyup] var [symtxt] = lib.mem.heapa(int8, [runningtally]) var [cpypos] = [&opaque](symtxt.ptr) [copiers] @[&int8](cpypos) = 0 return symtxt end rec.methods.send = terra([symself], [destcon], code: uint16, hd: lib.mem.ptr(lib.http.header)) lib.dbg(['transmitting template ' .. tid]) [tallyup] lib.net.mg_printf([destcon], 'HTTP/1.1 %s', lib.http.codestr(code)) for i = 0, hd.ct do lib.net.mg_printf([destcon], '%s: %s\r\n', hd.ptr[i].key, hd.ptr[i].value) end lib.net.mg_printf([destcon],'Content-Length: %llu\r\n\r\n', [runningtally] + 1) [senders] lib.net.mg_send([destcon],'\r\n',2) end return rec end return m |
Added view/docskel.tpl version [1d38dac966].
> > > > > > > > > > > |
1 2 3 4 5 6 7 8 9 10 11 |
<!doctype html> <html> <head> <title>@instance :: @title</title> <link rel="stylesheet" href="/style.css"> </head> <body> <h1>@title</h1> @body </body> </html> |
Added view/load.lua version [f2a65d7b61].
> > > > > > > > > > > > > > > > > > > > > > > > > |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
-- because lua can't scan directories, we need a -- file that indexes the templates manually, and -- copies them into a data structure we can then -- create templates from when we return to terra local path = ... local sources = { 'docskel'; 'tweet'; } local ingest = function(filename) local hnd = io.open(path..'/'..filename) local txt = hnd:read('*a') io.close(hnd) txt = txt:gsub('([^\\])!%b[]', '%1') txt = txt:gsub('([^\\])!!.-\n', '%1') txt = txt:gsub('\\(!%b[])', '%1') txt = txt:gsub('\\(!!)', '%1') return txt end local views = {} for _,n in pairs(sources) do views[n] = ingest(n .. '.tpl') end return views |
Added view/tweet.tpl version [59ae4e4ad9].
> > > > > > > > > > > > |
1 2 3 4 5 6 7 8 9 10 11 12 |
<div class="post"> <div class="detail"> <a class="username" href="@link"> <span class="nym">@nym</span> <span class="handle">[@handle]</span> </div> <div class="when">@when</div> </div> <div class="content"> <img class="avatar" src="@avatar"> <div class="text">@text</div> </div> </div> |