parsav  Diff

Differences From Artifact [d2f35b212c]:

To Artifact [889180c92d]:


     1      1   -- vim: ft=terra
     2      2   
     3      3   local util = dofile('common.lua')
     4      4   local buildopts, buildargs = util.parseargs{...}
            5  +config = dofile('config.lua')
     5      6   
     6         -local config = dofile('config.lua')
     7         -
     8         -local lib = {
            7  +lib = {
            8  +	init = {};
     9      9   	loadlib = function(name,hdr)
    10     10   		local p = config.pkg[name]
    11     11   		-- for _,v in pairs(p.dylibs) do
    12     12   		-- 	terralib.linklibrary(p.libdir .. '/' .. v)
    13     13   		-- end
    14     14   		return terralib.includec(p.incdir .. '/' .. hdr)
    15     15   	end;
    16         -	randomize = terralib.externfunction('getrandom', {&opaque, intptr, uint} -> ptrdiff);
           16  +	dispatch = function(tbl)
           17  +		return macro(function(v,...)
           18  +			for ty,fn in pairs(tbl) do
           19  +				if v.tree.type == ty then return fn(v,...) end
           20  +			end
           21  +			return (tbl[false])(v,...)
           22  +		end)
           23  +	end;
           24  +	emit = function(...)
           25  +		local code = {}
           26  +		for i,v in ipairs{...} do
           27  +			if type(v) == 'string' or type(v) == 'number' then
           28  +				local str = tostring(v)
           29  +				code[#code+1] = `lib.io.send(2, str, [#str])
           30  +			elseif v.tree:is 'constant' then
           31  +				local str = tostring(v:asvalue())
           32  +				code[#code+1] = `lib.io.send(2, str, [#str])
           33  +			else
           34  +				code[#code+1] = quote var n = v in
           35  +					lib.io.send(2, n, lib.str.sz(n)) end
           36  +			end
           37  +		end
           38  +		code[#code+1] = `lib.io.send(2, '\n', 1)
           39  +		return code
           40  +	end;
           41  +	proc = {
           42  +		exit = terralib.externfunction('exit', int -> {});
           43  +		getenv = terralib.externfunction('getenv', rawstring -> rawstring);
           44  +	};
           45  +	io = {
           46  +		open = terralib.externfunction('open', {rawstring, int} -> int);
           47  +		close = terralib.externfunction('close',  {int} -> int);
           48  +		send = terralib.externfunction('write', {int, rawstring, intptr} -> ptrdiff);
           49  +		recv = terralib.externfunction('read',  {int, rawstring, intptr} -> ptrdiff);
           50  +		say = macro(function(msg) return `lib.io.send(2, msg, [#(msg:asvalue())]) end);
           51  +		fmt = terralib.externfunction('printf',
           52  +			terralib.types.funcpointer({rawstring},{int},true));
           53  +	};
           54  +	str = {
           55  +		sz = terralib.externfunction('strlen', rawstring -> intptr);
           56  +		cmp = terralib.externfunction('strcmp', {rawstring, rawstring} -> int);
           57  +		cpy = terralib.externfunction('stpcpy',{rawstring, rawstring} -> rawstring);
           58  +		ncpy = terralib.externfunction('stpncpy',{rawstring, rawstring, intptr} -> rawstring);
           59  +		fmt = terralib.externfunction('asprintf',
           60  +			terralib.types.funcpointer({&rawstring},{int},true));
           61  +	};
           62  +	mem = {
           63  +		zero = macro(function(r)
           64  +			return quote
           65  +				for i = 0, [r.tree.type.N] do r[i] = 0 end
           66  +			end
           67  +		end);
           68  +		heapa_raw = terralib.externfunction('malloc', intptr -> &opaque);
           69  +		heapr_raw = terralib.externfunction('realloc', {&opaque, intptr} -> &opaque);
           70  +		heapf = terralib.externfunction('free', &opaque -> {});
           71  +		cpy = terralib.externfunction('mempcpy',{&opaque, &opaque, intptr} -> &opaque);
           72  +		heapa = macro(function(ty, sz)
           73  +			local p = lib.mem.ptr(ty:astype())
           74  +			return `p {
           75  +				ptr = [&ty:astype()](lib.mem.heapa_raw(sizeof(ty) * sz));
           76  +				ct = sz;
           77  +			}
           78  +		end)
           79  +	};
    17     80   }
           81  +
           82  +local noise = global(uint8,1)
           83  +local defrep = function(level,n,code)
           84  +	return macro(function(...)
           85  +		local q = lib.emit("\27["..code..";1m(parsav "..n..")\27[m ", ...)
           86  +		return quote
           87  +			if noise >= level then [q] end
           88  +		end
           89  +	end);
           90  +end
           91  +lib.dbg = defrep(3,'debug', '32')
           92  +lib.report = defrep(2,'info', '35')
           93  +lib.warn = defrep(1,'warn', '33')
           94  +lib.bail = macro(function(...)
           95  +	local q = lib.emit("\27[31;1m(parsav fatal)\27[m ", ...)
           96  +	return quote
           97  +		[q]
           98  +		lib.proc.exit(1)
           99  +	end
          100  +end);
          101  +lib.mem.ptr = terralib.memoize(function(ty)
          102  +	local t = terralib.types.newstruct(string.format('ptr<%s>', ty))
          103  +	t.entries = {
          104  +		{'ptr', &ty};
          105  +		{'ct', intptr};
          106  +	}
          107  +	local recurse = false
          108  +	if ty:isstruct() then
          109  +		if ty.methods.free then recurse = true end
          110  +	end
          111  +	t.methods = {
          112  +		free = terra(self: &t): bool
          113  +			[recurse and quote
          114  +				self.ptr:free()
          115  +			end or {}]
          116  +			if self.ct > 0 then
          117  +				lib.mem.heapf(self.ptr)
          118  +				self.ct = 0
          119  +				return true
          120  +			end
          121  +			return false
          122  +		end;
          123  +		init = terra(self: &t, newct: intptr): bool
          124  +			var nv = [&ty](lib.mem.heapa_raw(sizeof(ty) * newct))
          125  +			if nv ~= nil then
          126  +				self.ptr = nv
          127  +				self.ct = newct
          128  +				return true
          129  +			else return false end
          130  +		end;
          131  +		resize = terra(self: &t, newct: intptr): bool
          132  +			var nv: &ty
          133  +			if self.ct > 0
          134  +				then nv = [&ty](lib.mem.heapr_raw(self.ptr, sizeof(ty) * newct))
          135  +				else nv = [&ty](lib.mem.heapa_raw(sizeof(ty) * newct))
          136  +			end
          137  +			if nv ~= nil then
          138  +				self.ptr = nv
          139  +				self.ct = newct
          140  +				return true
          141  +			else return false end
          142  +		end;
          143  +	}
          144  +	return t
          145  +end)
          146  +
          147  +lib.err = lib.loadlib('mbedtls','mbedtls/error.h')
    18    148   lib.rsa = lib.loadlib('mbedtls','mbedtls/rsa.h')
    19    149   lib.pk = lib.loadlib('mbedtls','mbedtls/pk.h')
          150  +lib.md = lib.loadlib('mbedtls','mbedtls/md.h')
          151  +lib.b64 = lib.loadlib('mbedtls','mbedtls/base64.h')
          152  +lib.net = lib.loadlib('mongoose','mongoose.h')
          153  +lib.pq = lib.loadlib('libpq','libpq-fe.h')
          154  +lib.crypt = terralib.loadfile('crypt.t')()
          155  +lib.http = terralib.loadfile('http.t')()
          156  +lib.tpl = terralib.loadfile('tpl.t')()
          157  +lib.string = terralib.loadfile('string.t')()
          158  +lib.store = terralib.loadfile('store.t')()
          159  +lib.cmdparse = terralib.loadfile('cmdparse.t')()
    20    160   
    21         -local callbacks = {
    22         -	randomize = terra(ctx: &opaque, dest: &uint8, sz: intptr): int
    23         -		return lib.randomize(dest, sz, 0)
          161  +do local collate = function(path,f, ...)
          162  +	return loadfile(path..'/'..f..'.lua')(path, ...)
          163  +end
          164  +data = {
          165  +	view = collate('view','load');
          166  +} end
          167  +
          168  +-- slightly silly -- because we're using plain lua to gather up
          169  +-- the template sources, they have to be actually turned into
          170  +-- templates in the terra code, so we "mutate" them here
          171  +for k,v in pairs(data.view) do
          172  +	local t = lib.tpl.mk { body = v, id = 'view/'..k }
          173  +	data.view[k] = t
          174  +end
          175  +
          176  +local pemdump = macro(function(pub, kp)
          177  +	local msg = (pub:asvalue() and ' * emitting public key\n') or ' * emitting private key\n'
          178  +	return quote
          179  +		var buf: lib.crypt.pemfile
          180  +		lib.mem.zero(buf)
          181  +		lib.crypt.pem(pub, &kp, buf)
          182  +		lib.io.send(1, msg, [#msg])
          183  +		lib.io.send(1, [rawstring](&buf), lib.str.sz([rawstring](&buf)))
          184  +		lib.io.send(1, '\n', 1)
          185  +	end
          186  +end)
          187  +
          188  +local handle = {
          189  +	http = terra(con: &lib.net.mg_connection, event: int, p: &opaque, ext: &opaque)
          190  +		switch event do
          191  +			case lib.net.MG_EV_HTTP_MSG then
          192  +				lib.dbg('routing HTTP request')
          193  +				var msg = [&lib.net.mg_http_message](p)
          194  +
          195  +			end
          196  +		end
    24    197   	end;
    25    198   }
          199  +do
          200  +	local p = string.format('parsav: %s\nbuilt on %s\n', config.build.str, config.build.when)
          201  +	terra version() lib.io.send(1, p, [#p]) end
          202  +end
          203  +terra noise_init()
          204  +	var n = lib.proc.getenv('parsav_noise')
          205  +	if n ~= nil then
          206  +		if n[0] >= 0x30 and n[0] <= 0x39 and n[1] == 0 then
          207  +			noise = n[0] - 0x30
          208  +			return
          209  +		end
          210  +	end
          211  +	noise = 1
          212  +end
          213  +
          214  +local options = lib.cmdparse {
          215  +	version = {'V', 'display information about the binary build and exit'};
          216  +	quiet = {'q', 'do not print to standard out'};
          217  +	help = {'h', 'display this list'}
          218  +}
          219  +
          220  +terra entry(argc: int, argv: &rawstring): int
          221  +	noise_init()
          222  +	[lib.init]
          223  +
          224  +	var mode: options
          225  +	mode:parse(argc,argv)
          226  +	if mode.version then
          227  +		version()
          228  +		return 0
          229  +	end
          230  +	if mode.help then
          231  +		lib.io.send(1,  [options.helptxt], [#options.helptxt])
          232  +		return 0
          233  +	end
          234  +
          235  +	var bind = lib.proc.getenv('parsav_bind')
          236  +	if bind == nil then bind = '[::]:10917' end
          237  +
          238  +	var nm: lib.net.mg_mgr
          239  +	lib.net.mg_mgr_init(&nm)
          240  +
          241  +	var nmc = lib.net.mg_http_listen(&nm, bind, handle.http, nil)
          242  +
          243  +	while true do
          244  +		lib.net.mg_mgr_poll(&nm,1000)
          245  +	end
    26    246   
    27         -terra entry(): int
    28         -	var pk: lib.pk.mbedtls_pk_context
    29         -	lib.pk.mbedtls_pk_init(&pk)
    30         -	lib.pk.mbedtls_pk_setup(&pk, lib.pk.mbedtls_pk_info_from_type(lib.pk.MBEDTLS_PK_RSA))
    31         -	var rsa = [&lib.rsa.mbedtls_rsa_context](pk.pk_ctx)
    32         -	lib.rsa.mbedtls_rsa_gen_key(rsa, callbacks.randomize, nil, 2048, 65537)
          247  +	lib.net.mg_mgr_free(&nm)
    33    248   	return 0
    34    249   end
    35    250   
    36    251   local bflag = function(long,short)
    37    252   	if short and util.has(buildopts, short) then return true end
    38    253   	if long and util.has(buildopts, long) then return true end
    39    254   	return false
................................................................................
    45    260   end
    46    261   
    47    262   local emit = print
    48    263   if bflag('quiet','q') then emit = function() end end
    49    264   
    50    265   local out = config.exe and 'parsav' or 'parsav.o'
    51    266   local linkargs = {}
          267  +if config.posix then
          268  +	linkargs[#linkargs+1] = '-pthread'
          269  +end
    52    270   for _,p in pairs(config.pkg) do util.append(linkargs, p.linkargs) end
    53    271   emit('linking with args',util.dump(linkargs))
    54    272   terralib.saveobj(out, {
    55    273   		main = entry
    56    274   	},
    57    275   	linkargs,
    58    276   	config.tgttrip and terralib.newtarget {
    59    277   		Triple = config.tgttrip;
    60    278   		CPU = config.tgtcpu;
    61    279   		FloatABIHard = config.tgthf;
    62    280   	} or nil)