xref: /freebsd/contrib/lyaml/build-aux/luke (revision 2bc180ef045e5911cce0cea1c2a139cffd2b577a)
1*2bc180efSBaptiste Daroussin#!/usr/bin/env lua
2*2bc180efSBaptiste Daroussin--[[ minified code follows, see --help text for source location! ]]
3*2bc180efSBaptiste Daroussinlocal require=function(modname)if package.loaded[modname]==nil then
4*2bc180efSBaptiste Daroussinif type(package.preload[modname])~="function"then
5*2bc180efSBaptiste Daroussinio.stderr:write("module '" .. modname .. "' not found:\n   no valid field package.preload['" .. modname .. "']\n")
6*2bc180efSBaptiste Daroussinreturn nil
7*2bc180efSBaptiste Daroussinend
8*2bc180efSBaptiste Daroussinpackage.loaded[modname]=package.preload[modname](modname,"package.preload")end
9*2bc180efSBaptiste Daroussinreturn package.loaded[modname]end
10*2bc180efSBaptiste Daroussinpackage.preload['luke._base']=function()
11*2bc180efSBaptiste Daroussinlocal _ENV=require'std.normalize'{}local function fatal(...)local msg=(...)if select('#',...)>1 then
12*2bc180efSBaptiste Daroussinmsg=format(...)end
13*2bc180efSBaptiste Daroussinstderr:write('luke: fatal: '..msg..'\n')exit(1)end
14*2bc180efSBaptiste Daroussinreturn{diagnose=function(predicate,...)if not predicate then
15*2bc180efSBaptiste Daroussinfatal(...)end
16*2bc180efSBaptiste Daroussinend,fatal=fatal,}
17*2bc180efSBaptiste Daroussinend
18*2bc180efSBaptiste Daroussinpackage.preload['luke.cli']=function()
19*2bc180efSBaptiste Daroussinlocal _ENV=require'std.normalize'{'luke._base','luke.lukefile','luke.platforms','std.functional',}local function version()print[[
20*2bc180efSBaptiste Daroussinluke (Luke) 0.2.3
21*2bc180efSBaptiste DaroussinWritten by Gary V. Vaughan <gary@gnu.org>, 2014
22*2bc180efSBaptiste Daroussin
23*2bc180efSBaptiste DaroussinCopyright (C) 2022, Gary V. Vaughan
24*2bc180efSBaptiste DaroussinLuke comes with ABSOLUTELY NO WARRANTY.
25*2bc180efSBaptiste DaroussinYou may redistribute copies of Luke under the terms of the MIT license;
26*2bc180efSBaptiste Daroussinit may be used for any purpose at absolutely no cost, without permission.
27*2bc180efSBaptiste DaroussinSee <https://mit-license.org> for details.
28*2bc180efSBaptiste Daroussin]]exit(0)end
29*2bc180efSBaptiste Daroussinlocal function help()print[[
30*2bc180efSBaptiste DaroussinUsage: luke [OPTION]... [VAR=VALUE]... [TARGET]
31*2bc180efSBaptiste Daroussin
32*2bc180efSBaptiste DaroussinUse the source, Luke!
33*2bc180efSBaptiste Daroussin
34*2bc180efSBaptiste Daroussin  --help        print this help, then exit
35*2bc180efSBaptiste Daroussin  --version     print version number, then exit
36*2bc180efSBaptiste Daroussin  --file=FILE   use FILE instead of lukefile
37*2bc180efSBaptiste Daroussin  --value=NAME  print the value of variable NAME
38*2bc180efSBaptiste Daroussin  --quiet       without any output
39*2bc180efSBaptiste Daroussin  --verbose     provide more progress output
40*2bc180efSBaptiste Daroussin
41*2bc180efSBaptiste DaroussinEach TARGET can be one of the module table keys from lukefile, or:
42*2bc180efSBaptiste Daroussin
43*2bc180efSBaptiste Daroussin  all           build all targets in lukefile
44*2bc180efSBaptiste Daroussin  install       copy all built targets to $PREFIX
45*2bc180efSBaptiste Daroussin
46*2bc180efSBaptiste DaroussinIf no TARGET is given, 'all' is implied.
47*2bc180efSBaptiste Daroussin
48*2bc180efSBaptiste DaroussinReport bugs to https://github.com/gvvaughan/luke/issues.]]exit(0)end
49*2bc180efSBaptiste Daroussinlocal function opterr(...)local msg=(...)if select('#',...)>1 then
50*2bc180efSBaptiste Daroussinmsg=format(...)end
51*2bc180efSBaptiste Daroussinmsg=gsub(msg,'%.$','')stderr:write('luke: error: '..msg..'.\n')stderr:write("luke: try '"..arg[0].." --help' for help.\n")exit(2)end
52*2bc180efSBaptiste Daroussinlocal function display(...)return stdout:write(concat{...})end
53*2bc180efSBaptiste Daroussinlocal function dump(...)local s=concat(map(list(...),str))if len(s)>0 then
54*2bc180efSBaptiste Daroussingsub(concat(map(list(...),str)),'\n*$','\n'):gsub('(.-)\n',function(line)stderr:write('   DEBUG: '..line..'\n')end)end
55*2bc180efSBaptiste Daroussinend
56*2bc180efSBaptiste Daroussinlocal function interpolate_to_substitute(s)return(gsub(s,'%$([%w_]+)','@%1@'))end
57*2bc180efSBaptiste Daroussinreturn{parse_arguments=function(args)local r={clidefs={},valreqs={},fname='lukefile',install={},log=nop,targets={},verbose=nop,write=display,}map(args,function(opt)case(opt,{['--debug']=function()r.log=dump
58*2bc180efSBaptiste Daroussinend,['%-%-file=(.+)']=function(optarg)r.fname=optarg
59*2bc180efSBaptiste Daroussinend,['%-%-value=(.+)']=function(optarg)r.valreqs[#r.valreqs+1]=optarg
60*2bc180efSBaptiste Daroussinend,['--quiet']=function()r.write=nop
61*2bc180efSBaptiste Daroussinend,['--verbose']=function()r.verbose=display
62*2bc180efSBaptiste Daroussinend,['--help']=help,['--version']=version,['([^-][^=]-)=(.+)']=function(name,value)r.clidefs[name]=value
63*2bc180efSBaptiste Daroussinend,function(opt)if match(opt,'^-')~=nil then
64*2bc180efSBaptiste Daroussinopterr("unrecognized option '%s'",opt)end
65*2bc180efSBaptiste Daroussinappend(r.targets,opt)end,})end)return r
66*2bc180efSBaptiste Daroussinend,validate_arguments=function(parsed)local luke,err=loadluke(parsed.fname)diagnose(luke~=nil,'bad %s: %s',parsed.fname,err)if isempty(luke.modules or{})then
67*2bc180efSBaptiste Daroussinfatal("no modules table in '%s', nothing to build",parsed.fname)end
68*2bc180efSBaptiste Daroussinlocal targets=call(function()if isempty(parsed.targets)or contains(parsed.targets,'all')then
69*2bc180efSBaptiste Daroussinreturn except(flatten(parsed.targets,keys(luke.modules)),'all')end
70*2bc180efSBaptiste Daroussinlocal r=filter(parsed.targets,function(target)if target~='install'and luke.modules[target]==nil then
71*2bc180efSBaptiste Daroussinfatal("no rule to make target '%s'",target)end
72*2bc180efSBaptiste Daroussinreturn true
73*2bc180efSBaptiste Daroussinend)assert(len(r)>0,"no build targets specified")return r
74*2bc180efSBaptiste Daroussinend)local install
75*2bc180efSBaptiste Daroussinlocal build=pluck(targets,luke.modules)if contains(targets,'install')then
76*2bc180efSBaptiste Daroussininstall=build or luke.modules
77*2bc180efSBaptiste Daroussinend
78*2bc180efSBaptiste Daroussinluke.modules=build
79*2bc180efSBaptiste Daroussinif isempty(luke.modules)then
80*2bc180efSBaptiste Daroussinluke.external_dependencies=nil
81*2bc180efSBaptiste Daroussinend
82*2bc180efSBaptiste Daroussinluke.substitute=merge(luke.substitute or{},{package=interpolate_to_substitute(luke.package),version=interpolate_to_substitute(luke.version),})luke.variables=merge(luke.variables or{},collect_variables(luke),{LUA_DIR='/usr',LUA_BINDIR='$LUA_DIR/bin',LUA_INCDIR='$LUA_DIR/include/lua$LUAVERSION',LUA_LIBDIR='$LUA_DIR/lib',objdir=platforms[1],package=luke.package,version=luke.version,})return{clidefs=parsed.clidefs,install=install,log=parsed.log,luke=luke,valreqs=parsed.valreqs,verbose=parsed.verbose,write=parsed.write,}end,}
83*2bc180efSBaptiste Daroussinend
84*2bc180efSBaptiste Daroussinpackage.preload['luke.compile']=function()
85*2bc180efSBaptiste Daroussinlocal _ENV=require'std.normalize'{'luke._base','luke.environment','std.functional','type.context-manager','type.path',SHELLMETACHARS='[%s%$"]',}local function spawn(env,...)local command=interpolate(env,concat({...},' '))return with(TmpFile(),TmpFile(),function(out,err)local pipe=concat{command,' >',out.filename,' 2>',err.filename,'; printf $?'}return tonumber(slurp(Pipe(pipe))),slurp(File(err.filename)),slurp(File(out.filename))end)end
86*2bc180efSBaptiste Daroussinlocal function run(L,env,command)L.write(interpolate(env,concat(command,' ')),'\n')local status,err,out=spawn(env,unpack(command))if status~=0 then
87*2bc180efSBaptiste Daroussinif L.write==nop then
88*2bc180efSBaptiste Daroussinstdout:write(concat(command,' ')..'\n')end
89*2bc180efSBaptiste Daroussinstderr:write(err..'\n')end
90*2bc180efSBaptiste Daroussinreturn status,out,err
91*2bc180efSBaptiste Daroussinend
92*2bc180efSBaptiste Daroussinlocal function defines(env,deftables)return zip_with(merge({},unpack(deftables)),function(name,value)local fmt=cond({[int(value)==1]='-D%s'},{[match(value,SHELLMETACHARS)~=nil]="-D%s='%s'"},{[true]='-D%s=%s'})return format(fmt,name,value)end)end
93*2bc180efSBaptiste Daroussinlocal function incdirs(...)return map(flatten(...),function(v)return'-I'..v
94*2bc180efSBaptiste Daroussinend)end
95*2bc180efSBaptiste Daroussinlocal function libdirs(...)return map(flatten(...),function(v)return'-L'..v
96*2bc180efSBaptiste Daroussinend)end
97*2bc180efSBaptiste Daroussinlocal function c_module_path(objdir,name)return format('%s/%s.$LIB_EXTENSION',objdir,gsub(name,'%.','/'))end
98*2bc180efSBaptiste Daroussinlocal function c_source(module,objdir)local path=gsub(module,'%.','/')local src=c_module_path(objdir,path)return src,(gsub('$INST_LIBDIR/'..path,'/[^/]+$',''))end
99*2bc180efSBaptiste Daroussinlocal function lua_source(module,src)local abspath='$INST_LUADIR/'..gsub(module,'%.','/')if match(src,'/init%.lua$')then
100*2bc180efSBaptiste Daroussinabspath=abspath..'/init'end
101*2bc180efSBaptiste Daroussinabspath=abspath..'.lua'return src,(gsub(abspath,'/[^/]+%.lua$',''))end
102*2bc180efSBaptiste Daroussinlocal function module_to_path(module,sources,objdir)return dropuntil(sources,function(source)return case(source,{['.*%.[ch]']=bind(c_source,{module,objdir}),['(.*%.[ch])%.in']=bind(c_source,{module,objdir}),['.*%.lua']=bind(lua_source,{module}),['(.*%.lua)%.in']=bind(lua_source,{module}),function(src)fatal("unsupported source type '%s'",src)end,})end)end
103*2bc180efSBaptiste Daroussinreturn{build_c_module=function(L,env,luke,name)local rules=luke.modules[name]local c_module=c_module_path(luke.variables.objdir,name)local command={'$MAKEDIRS',dirname(c_module)}local status,err,out=spawn(env,unpack(command))if status~=0 then
104*2bc180efSBaptiste Daroussinstdout:write(concat(command,' ')..'\n')stderr:write(err..'\n')exit(status)end
105*2bc180efSBaptiste Daroussinreturn run(L,env,flatten('$CC $CFLAGS $LIBFLAG $PKGFLAGS $CPPFLAGS',defines(env,except(list(rules.defines,luke.defines),nil)),incdirs(rules.incdirs,luke.incdirs),rules.sources,'-o',c_module,'$LDFLAGS',libdirs(rules.libdirs,luke.libdirs),'$LIBS',rules.libraries,luke.libraries))end,c_modules=function(modules)return filter(keys(modules),function(name)return dropuntil(modules[name].sources,bind(match,{[2]='%.[ch]$'}))end)end,incdirs=incdirs,install_modules=function(L,env,luke,modules)return reduce(keys(modules),0,function(status,name)if status==0 then
106*2bc180efSBaptiste Daroussinlocal src,dir=module_to_path(name,modules[name].sources,luke.variables.objdir)if not exists(interpolate(env,dir))then
107*2bc180efSBaptiste Daroussinstatus=run(L,env,{'$MAKEDIRS',dir})end
108*2bc180efSBaptiste Daroussinif status==0 then
109*2bc180efSBaptiste Daroussinstatus=run(L,env,{'$INSTALL',src,dir..'/'})end
110*2bc180efSBaptiste Daroussinend
111*2bc180efSBaptiste Daroussinreturn status
112*2bc180efSBaptiste Daroussinend)end,libdirs=libdirs,run_command=run,spawn=spawn,}
113*2bc180efSBaptiste Daroussinend
114*2bc180efSBaptiste Daroussinpackage.preload['luke.configure']=function()
115*2bc180efSBaptiste Daroussinlocal _ENV=require'std.normalize'{'luke._base','luke.compile','luke.environment','std.functional','type.context-manager','type.dict',CCPROGS={'cc','gcc','clang'},}local function logspawn(L,env,...)local status,err=spawn(env,...)if status~=0 and err~=''then
116*2bc180efSBaptiste DaroussinL.log(err)end
117*2bc180efSBaptiste Daroussinreturn status
118*2bc180efSBaptiste Daroussinend
119*2bc180efSBaptiste Daroussinlocal function checking(L,...)L.verbose('checking ',concat({...},' '),'... ')end
120*2bc180efSBaptiste Daroussinlocal function found_library(L,x)if x==nil or x==''then
121*2bc180efSBaptiste DaroussinL.verbose'none required'elseif isempty(x)then
122*2bc180efSBaptiste DaroussinL.verbose'not supported'else
123*2bc180efSBaptiste DaroussinL.verbose(x)end
124*2bc180efSBaptiste DaroussinL.verbose'\n'return x
125*2bc180efSBaptiste Daroussinend
126*2bc180efSBaptiste Daroussinlocal function found_prog(L,x)L.verbose(x and'yes\n'or'no\n')return x
127*2bc180efSBaptiste Daroussinend
128*2bc180efSBaptiste Daroussinlocal function found_result(L,x)L.verbose(x==0 and'yes\n'or'no\n')return x~=0 and 0 or 1
129*2bc180efSBaptiste Daroussinend
130*2bc180efSBaptiste Daroussinlocal function bindirs(...)return map(flatten(...),function(v)return v..':'end)end
131*2bc180efSBaptiste Daroussinlocal function compile_command(L,env,config,filename)local command=flatten('$CC','-c','$CFLAGS',incdirs(config.incdir),'$CPPFLAGS',filename)L.log(interpolate(env,concat(command,' ')))return unpack(command)end
132*2bc180efSBaptiste Daroussinlocal function link_command(L,env,config,a_out,source,lib)local command=flatten('$CC','$CFLAGS',incdirs(config.incdir),'$CPPFLAGS','-o',a_out,source,libdirs(config.libdir),'$LDFLAGS',lib,'$libs',CONFIGENV.libs)L.log(interpolate(env,concat(command,' ')))return unpack(command)end
133*2bc180efSBaptiste Daroussinlocal function check_executable_in_path(L,env,config,prog)local PATH=concat(bindirs(config.bindir))..getenv('PATH')local found=dropuntil(gmatch(PATH,'[^:]+'),function(path)local progpath=path..'/'..prog
134*2bc180efSBaptiste Daroussinreturn with(File(progpath,'r'),function(h)return h and isfile(h.context)and progpath or nil
135*2bc180efSBaptiste Daroussinend)end)L.log(found and'found '..found or prog..' not found')return found~=nil
136*2bc180efSBaptiste Daroussinend
137*2bc180efSBaptiste Daroussinlocal function check_header_compile(L,env,config,header,extra_hdrs)return with(CTest(),function(conftest)conftest:write(format('%s\n#include "%s"\n',extra_hdrs,header))return logspawn(L,env,compile_command(L,env,config,conftest.filename))end)end
138*2bc180efSBaptiste Daroussinlocal function check_struct_member_compile(L,env,config,structname,member,extra_hdrs)return with(CTest(),function(conftest)conftest:write(format([[
139*2bc180efSBaptiste Daroussin%s
140*2bc180efSBaptiste Daroussinint main () {
141*2bc180efSBaptiste Daroussinstatic %s aggr;
142*2bc180efSBaptiste Daroussinif (sizeof aggr.%s)
143*2bc180efSBaptiste Daroussin    return 0;
144*2bc180efSBaptiste Daroussinreturn 0;
145*2bc180efSBaptiste Daroussin}
146*2bc180efSBaptiste Daroussin]],extra_hdrs,structname,member))return logspawn(L,env,compile_command(L,env,config,conftest.filename))end)end
147*2bc180efSBaptiste Daroussinlocal function try_link(L,env,config,lib,symbol)return with(CTest(),TmpFile(),function(conftest,a_out)conftest:write(format([[
148*2bc180efSBaptiste Daroussin/* Override any GCC internal prototype to avoid an error.
149*2bc180efSBaptiste Daroussin Use char because int might match the return type of a GCC
150*2bc180efSBaptiste Daroussin builtin and then its argument prototype would still apply.   */
151*2bc180efSBaptiste Daroussinchar %s ();
152*2bc180efSBaptiste Daroussinint main () {
153*2bc180efSBaptiste Daroussinreturn %s ();
154*2bc180efSBaptiste Daroussin}
155*2bc180efSBaptiste Daroussin]],symbol,symbol))return logspawn(L,env,link_command(L,env,config,a_out.filename,conftest.filename,lib))end)end
156*2bc180efSBaptiste Daroussinlocal function try_compile(L,env,config,headers)return with(CTest(),TmpFile(),function(conftest,a_out)conftest:write(format([[
157*2bc180efSBaptiste Daroussin%s
158*2bc180efSBaptiste Daroussin#if !defined %s || %s == -1
159*2bc180efSBaptiste Daroussinchoke me
160*2bc180efSBaptiste Daroussin#endif
161*2bc180efSBaptiste Daroussinint
162*2bc180efSBaptiste Daroussinmain()
163*2bc180efSBaptiste Daroussin{
164*2bc180efSBaptiste Daroussinreturn 0;
165*2bc180efSBaptiste Daroussin}
166*2bc180efSBaptiste Daroussin]],headers,config.ifdef,config.ifdef))return logspawn(L,env,link_command(L,env,config,a_out.filename,conftest.filename))end)end
167*2bc180efSBaptiste Daroussinlocal function check_func_decl(L,env,config,fname,extra_hdrs)return with(CTest(),function(conftest)conftest:write(format([[
168*2bc180efSBaptiste Daroussin%s
169*2bc180efSBaptiste Daroussinint
170*2bc180efSBaptiste Daroussinmain()
171*2bc180efSBaptiste Daroussin{
172*2bc180efSBaptiste Daroussin#ifndef %s
173*2bc180efSBaptiste Daroussin(void) %s;
174*2bc180efSBaptiste Daroussin#endif
175*2bc180efSBaptiste Daroussinreturn 0;
176*2bc180efSBaptiste Daroussin}
177*2bc180efSBaptiste Daroussin]],extra_hdrs,fname,fname))return logspawn(L,env,compile_command(L,env,config,conftest.filename))end)end
178*2bc180efSBaptiste Daroussinlocal function check_func_link(L,env,config,fname)return with(CTest(),TmpFile(),function(conftest,a_out)conftest:write(format([[
179*2bc180efSBaptiste Daroussin/* Define to an innocous variant, in case <limits.h> declares it.
180*2bc180efSBaptiste Daroussin For example, HP-UX 11i <limits,h> declares gettimeofday.   */
181*2bc180efSBaptiste Daroussin#define %s innocuous_%s
182*2bc180efSBaptiste Daroussin
183*2bc180efSBaptiste Daroussin/* System header to define __stub macros and hopefully few prototypes,
184*2bc180efSBaptiste Daroussin which can conflict with declaration below.
185*2bc180efSBaptiste Daroussin Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
186*2bc180efSBaptiste Daroussin <limits.h> exists even on freestanding compilers.   */
187*2bc180efSBaptiste Daroussin
188*2bc180efSBaptiste Daroussin#ifdef __STDC__
189*2bc180efSBaptiste Daroussin# include <limits.h>
190*2bc180efSBaptiste Daroussin#else
191*2bc180efSBaptiste Daroussin# include <assert.h>
192*2bc180efSBaptiste Daroussin#endif
193*2bc180efSBaptiste Daroussin
194*2bc180efSBaptiste Daroussin#undef %s
195*2bc180efSBaptiste Daroussin
196*2bc180efSBaptiste Daroussin/* Override any GCC internal prototype to avoid an error.
197*2bc180efSBaptiste Daroussin Use char because int might match the return type of a GCC
198*2bc180efSBaptiste Daroussin builtin and then its argument prototype would still apply.   */
199*2bc180efSBaptiste Daroussinchar %s ();
200*2bc180efSBaptiste Daroussin
201*2bc180efSBaptiste Daroussin/* The GNU C library defines this for functions which it implements
202*2bc180efSBaptiste Daroussin to always fail with ENOSYS.   Some functions are actually named
203*2bc180efSBaptiste Daroussin something starting with __ and the normal name is an alias.   */
204*2bc180efSBaptiste Daroussin#if defined __stub_%s || defined __stub__%s
205*2bc180efSBaptiste Daroussinchoke me
206*2bc180efSBaptiste Daroussin#endif
207*2bc180efSBaptiste Daroussin
208*2bc180efSBaptiste Daroussinint main () {
209*2bc180efSBaptiste Daroussinreturn %s ();
210*2bc180efSBaptiste Daroussin}
211*2bc180efSBaptiste Daroussin]],fname,fname,fname,fname,fname,fname,fname))return logspawn(L,env,link_command(L,env,config,a_out.filename,conftest.filename))end)end
212*2bc180efSBaptiste Daroussinlocal function add_external_deps(env,config,prefix)if prefix~=nil then
213*2bc180efSBaptiste Daroussinfor k,v in next,{bindir='$%s_BINDIR',incdir='$%s_INCDIR',libdir='$%s_LIBDIR'}do
214*2bc180efSBaptiste Daroussinlocal envvar=interpolate(env,format(v,prefix))if envvar~=''then
215*2bc180efSBaptiste Daroussinconfig[k]=envvar
216*2bc180efSBaptiste Daroussinend
217*2bc180efSBaptiste Daroussinend
218*2bc180efSBaptiste Daroussinend
219*2bc180efSBaptiste Daroussinend
220*2bc180efSBaptiste Daroussinlocal function format_includes(includes)return map(includes or{},function(include)return format('#include "%s"',include)end)end
221*2bc180efSBaptiste Daroussinlocal configure=setmetatable(OrderedDict({checkprog=function(L,env,config)return dropuntil(config.progs,function(prog)checking(L,'for',prog)if found_prog(L,check_executable_in_path(L,env,config,prog))then
222*2bc180efSBaptiste Daroussinreturn prog
223*2bc180efSBaptiste Daroussinend
224*2bc180efSBaptiste Daroussinend)or fatal('cannot find '..config.checkprog)end},{checkheader=function(L,env,config)checking(L,'for',config.checkheader)local extra_hdrs=concat(format_includes(config.includes),'\n')return found_result(L,check_header_compile(L,env,config,config.checkheader,extra_hdrs))end},{checkdecl=function(L,env,config)checking(L,'whether',config.checkdecl,'is declared')local extra_hdrs=concat(format_includes(config.includes),'\n')return found_result(L,check_func_decl(L,env,config,config.checkdecl,extra_hdrs))end},{checksymbol=function(L,env,config)checking(L,'for library containing',config.checksymbol)if config.ifdef~=nil then
225*2bc180efSBaptiste Daroussinlocal headers=concat(format_includes(config.includes),'\n')if try_compile(L,env,config,headers)~=0 then
226*2bc180efSBaptiste Daroussinreturn found_library(L,{})end
227*2bc180efSBaptiste Daroussinend
228*2bc180efSBaptiste Daroussinlocal libraries,symbol=config.libraries,config.checksymbol
229*2bc180efSBaptiste Daroussinlocal trylibs=reduce(libraries,{''},function(r,lib)append(r,'-l'..lib)end)return dropuntil(trylibs,function(lib)if try_link(L,env,config,lib,symbol)==0 then
230*2bc180efSBaptiste Daroussinif lib~=''then
231*2bc180efSBaptiste Daroussinif CONFIGENV.libs~=''then
232*2bc180efSBaptiste DaroussinCONFIGENV.libs=' '..CONFIGENV.libs
233*2bc180efSBaptiste Daroussinend
234*2bc180efSBaptiste DaroussinCONFIGENV.libs=lib..CONFIGENV.libs
235*2bc180efSBaptiste Daroussinend
236*2bc180efSBaptiste Daroussinreturn found_library(L,lib)end
237*2bc180efSBaptiste Daroussinend)or call(function()L.verbose'\n'fatal("required symbol '%s' not found in any of libc, lib%s",symbol,concat(libraries,', lib'))end)end},{checkfunc=function(L,env,config)checking(L,'for',config.checkfunc)return found_result(L,check_func_link(L,env,config,config.checkfunc))end},{checkmember=function(L,env,config)checking(L,'for',config.checkmember)local extra_hdrs=concat(format_includes(config.includes),'\n')local i=find(config.checkmember,'%.')local structname=sub(config.checkmember,1,i-1)local member=sub(config.checkmember,i+1)return found_result(L,check_struct_member_compile(L,env,config,structname,member,extra_hdrs))end}),{__call=function(self,L,env,config,prefix)return case(type(config),{['number']=function()return str(config)end,['string']=function()return config
238*2bc180efSBaptiste Daroussinend,['table']=function()return dropuntil(self,function(fname)if config[fname]~=nil then
239*2bc180efSBaptiste Daroussinadd_external_deps(env,config,prefix)return apply(self[fname],list(L,env,config))end
240*2bc180efSBaptiste Daroussinend)or fatal("unable to configure with keys '%s'",concat(keys(config),"', '"))end,function(type)fatal("unsupported configure type '%s'",type)end,})end,})return{config_compiler=function(L,env)local CC=env.CC
241*2bc180efSBaptiste Daroussinif CC==nil then
242*2bc180efSBaptiste DaroussinCC=configure(L,env,{checkprog='C compiler',progs=CCPROGS})env=makeenv(env,{CC=CC})end
243*2bc180efSBaptiste Daroussinchecking(L,interpolate(env,'whether $CC works'))local cm=CTest()local works,err=with(cm,function(conftest)conftest:write('typedef int x;\n')return spawn(env,'$compile',conftest.filename)end)if works~=0 then
244*2bc180efSBaptiste DaroussinL.verbose'no\n'L.log(interpolate(env,'$compile '..cm.filename))if err and err~=''then
245*2bc180efSBaptiste DaroussinL.log(err)end
246*2bc180efSBaptiste Daroussinfatal('could not find a working C compiler')end
247*2bc180efSBaptiste Daroussinfound_prog(L,CC)return env
248*2bc180efSBaptiste Daroussinend,config_ldoc=function(L,env)local LDOC=env.LDOC
249*2bc180efSBaptiste Daroussinif LDOC==nil then
250*2bc180efSBaptiste DaroussinLDOC=configure(L,env,{checkprog='LDocs generator',progs={'ldoc','true'}})env=makeenv(env,{LDOC=LDOC})end
251*2bc180efSBaptiste Daroussinreturn env
252*2bc180efSBaptiste Daroussinend,configure=configure,}
253*2bc180efSBaptiste Daroussinend
254*2bc180efSBaptiste Daroussinpackage.preload['luke.environment']=function()
255*2bc180efSBaptiste Daroussinlocal _ENV=require'std.normalize'{'luke.platforms','std.functional',LUAVERSION=string.gsub(_VERSION,'[^0-9%.]+',''),}local env_mt={__index=function(self,varname)return dropuntil(self,function(env)local value=env[varname]if value~=nil then
256*2bc180efSBaptiste Daroussinself[varname]=value
257*2bc180efSBaptiste Daroussinreturn value
258*2bc180efSBaptiste Daroussinend
259*2bc180efSBaptiste Daroussinend)end,}local function interpolate_with(pattern,env,s)local r=''while r~=s do
260*2bc180efSBaptiste Daroussinr=s
261*2bc180efSBaptiste Daroussins=gsub(r,pattern,function(varname)return env[varname]or''end)end
262*2bc180efSBaptiste Daroussinreturn r
263*2bc180efSBaptiste Daroussinend
264*2bc180efSBaptiste Daroussinlocal function isenv(t)return getmetatable(t)==env_mt
265*2bc180efSBaptiste Daroussinend
266*2bc180efSBaptiste Daroussinreturn{CONFIGENV={compile='$CC -c $CFLAGS $CPPFLAGS',libs='',link='$CC $CFLAGS $CPPFLAGS $LDFLAGS',},DEFAULTENV=filter_platforms{LUAVERSION=LUAVERSION,PREFIX='/usr/local',INST_LIBDIR='$PREFIX/lib/lua/$LUAVERSION',INST_LUADIR='$PREFIX/share/lua/$LUAVERSION',LIB_EXTENSION='so',OBJ_EXTENSION='o',INSTALL='cp',MAKEDIRS='mkdir -p',CFLAGS='-O2',platforms={macosx={LIBFLAG='-fPIC -bundle -undefined dynamic_lookup -all_load',},LIBFLAG='-shared -fPIC',},},SHELLENV=setmetatable({},{__index=function(_,v)return getenv(v)end,}),expand=bind(interpolate_with,{'@([^@]+)@'}),interpolate=bind(interpolate_with,{'%$([%w_]+)'}),makeenv=function(...)local env=reduce(except(list(...),nil),function(r,t)if isenv(t)then
267*2bc180efSBaptiste Daroussinmap(t,bind(append,{r}))else
268*2bc180efSBaptiste Daroussinappend(r,t)end
269*2bc180efSBaptiste Daroussinend)return setmetatable(env,env_mt)end,}
270*2bc180efSBaptiste Daroussinend
271*2bc180efSBaptiste Daroussinpackage.preload['luke']=function()
272*2bc180efSBaptiste Daroussinlocal _ENV=require'std.normalize'{'luke.cli','luke.compile','luke.configure','luke.environment','luke.lukefile','std.functional',}local function run_ldocs(L,env,ldocs)return run_command(L,env,flatten{'$LDOC -c',ldocs.sources,'.'})end
273*2bc180efSBaptiste Daroussinlocal function build_modules(L,env)local conf=makeenv(CONFIGENV,env)if not isempty(L.luke.ldocs or{})then
274*2bc180efSBaptiste Daroussinconf=config_ldoc(L,conf)env=makeenv(env,{LDOC=conf.LDOC})end
275*2bc180efSBaptiste Daroussinlocal c=c_modules(L.luke.modules)if not isempty(c)then
276*2bc180efSBaptiste Daroussinconf=config_compiler(L,conf)env=makeenv(env,{CC=conf.CC})end
277*2bc180efSBaptiste DaroussinL.luke=run_configs(L,conf,L.luke)local substitute=makeenv(L.clidefs,L.luke.substitute,SHELLENV)L.luke=run_templates(L,substitute,L.luke)local status=dropuntil(c,isnonzero,function(name)return build_c_module(L,env,L.luke,name)end)or 0
278*2bc180efSBaptiste Daroussinif status==0 and not isempty(L.luke.ldocs or{})then
279*2bc180efSBaptiste Daroussinstatus=run_ldocs(L,env,L.luke.ldocs)end
280*2bc180efSBaptiste Daroussinreturn status
281*2bc180efSBaptiste Daroussinend
282*2bc180efSBaptiste Daroussinreturn{main=function(args)local L=validate_arguments(parse_arguments(args))local env=makeenv(L.clidefs,L.luke.variables,DEFAULTENV,SHELLENV)local status=0
283*2bc180efSBaptiste Daroussinif not isempty(L.valreqs)then
284*2bc180efSBaptiste Daroussinmap(L.valreqs,function(name)print(interpolate(env,concat{name,"='$",name,"'"}))end)exit(0)end
285*2bc180efSBaptiste Daroussinif status==0 and not isempty(L.luke.modules or{})then
286*2bc180efSBaptiste Daroussinstatus=build_modules(L,env)end
287*2bc180efSBaptiste Daroussinif status==0 then
288*2bc180efSBaptiste Daroussinstatus=install_modules(L,env,L.luke,L.install)end
289*2bc180efSBaptiste Daroussinreturn status
290*2bc180efSBaptiste Daroussinend,}
291*2bc180efSBaptiste Daroussinend
292*2bc180efSBaptiste Daroussinpackage.preload['luke.lukefile']=function()
293*2bc180efSBaptiste Daroussinlocal _ENV=require'std.normalize'{'luke._base','luke.configure','luke.environment','luke.platforms','std.functional','type.context-manager',}local function has_anykey(t,keylist)return any(map(keylist,function(k)return t[k]~=nil
294*2bc180efSBaptiste Daroussinend))end
295*2bc180efSBaptiste Daroussinlocal function isconfig(x)return istable(x)and has_anykey(x,configure)end
296*2bc180efSBaptiste Daroussinlocal function collect_configs(luke,modulename,configs)configs=configs or{}for k,v in next,luke do
297*2bc180efSBaptiste Daroussinif isconfig(v)then
298*2bc180efSBaptiste Daroussinappend(configs,{t=luke,k=k,module=modulename})elseif istable(v)then
299*2bc180efSBaptiste Daroussinif k=='modules'or k=='external_dependencies'then
300*2bc180efSBaptiste Daroussinfor name,rules in next,v do
301*2bc180efSBaptiste Daroussincollect_configs(rules,name,configs)end
302*2bc180efSBaptiste Daroussinelse
303*2bc180efSBaptiste Daroussincollect_configs(v,modulename,configs)end
304*2bc180efSBaptiste Daroussinend
305*2bc180efSBaptiste Daroussinend
306*2bc180efSBaptiste Daroussinreturn configs
307*2bc180efSBaptiste Daroussinend
308*2bc180efSBaptiste Daroussinlocal function deepcopy(t)return mapvalues(t,function(v)return case(type(v),{['table']=function()return deepcopy(v)end,v,})end)end
309*2bc180efSBaptiste Daroussinlocal weighting=setmetatable(copy(configure),{__call=function(self,config)local t=config.t[config.k]for i=1,len(self)do
310*2bc180efSBaptiste Daroussinif t[self[i]]~=nil then
311*2bc180efSBaptiste Daroussinreturn i
312*2bc180efSBaptiste Daroussinend
313*2bc180efSBaptiste Daroussinend
314*2bc180efSBaptiste Daroussinend})local function config_cmp(a,b)return weighting(a)<weighting(b)end
315*2bc180efSBaptiste Daroussinlocal function fill_templates(env,src,dest)with(File(dest,'w'),function(cm)for line in lines(src)do
316*2bc180efSBaptiste Daroussincm:write(expand(env,line)..'\n')end
317*2bc180efSBaptiste Daroussinend)return dest
318*2bc180efSBaptiste Daroussinend
319*2bc180efSBaptiste Daroussinlocal function rewrite_template_files(L,env,source)return case(source,{['(.+)%.in']=function(r)L.write('creating '..r..'\n')return fill_templates(env,r..'.in',r)end,source,})end
320*2bc180efSBaptiste Daroussinlocal function collect_variables(luke,variables)for k,v in next,luke do
321*2bc180efSBaptiste Daroussinif k=='external_dependencies'then
322*2bc180efSBaptiste Daroussinmap(keys(v),function(name)local rootdir=concat{'$',name,'_DIR'}variables[name..'_DIR']='/usr'variables[name..'_BINDIR']=rootdir..'/bin'variables[name..'_INCDIR']=rootdir..'/include'variables[name..'_LIBDIR']=rootdir..'/lib'end)elseif istable(v)then
323*2bc180efSBaptiste Daroussincollect_variables(v,variables)end
324*2bc180efSBaptiste Daroussinend
325*2bc180efSBaptiste Daroussinreturn variables
326*2bc180efSBaptiste Daroussinend
327*2bc180efSBaptiste Daroussinlocal function normalize_configs(config)return cond({[not istable(config)]=config,},{[not isconfig(config)]=function()return mapvalues(config,normalize_configs)end,},{[true]=function()local keymap={include='includes',prog='progs',library='libraries',}return foldkeys(keymap,config,function(a,b)local r=istable(a)and copy(a)or{a}b=istable(b)and b or{b}return reduce(b,r,function(v)append(r,v)end)end)end,})end
328*2bc180efSBaptiste Daroussinlocal function normalize_rules(rules)return case(type(rules),{['nil']=nop,['string']=function()return{sources={rules}}end,['table']=function()if len(rules)>0 then
329*2bc180efSBaptiste Daroussinreturn{sources=rules}elseif isstring(rules.sources)then
330*2bc180efSBaptiste Daroussinreturn merge({sources={rules.sources}},normalize_configs(rules))end
331*2bc180efSBaptiste Daroussinreturn normalize_configs(rules)end,function(v)fatal("unsupported rule type '%s'",v)end,})end
332*2bc180efSBaptiste Daroussinlocal function unwrap_external_dependencies(luke)if istable(luke.external_dependencies)then
333*2bc180efSBaptiste Daroussinfor prefix,config in next,luke.external_dependencies do
334*2bc180efSBaptiste Daroussinif istable(config)and next(config)and config.library~=''then
335*2bc180efSBaptiste Daroussinluke.incdirs=append(luke.incdirs or{},format('$%s_INCDIR',prefix))luke.libdirs=append(luke.libdirs or{},format('$%s_LIBDIR',prefix))luke.libraries=append(luke.libraries or{},config.library)end
336*2bc180efSBaptiste Daroussinend
337*2bc180efSBaptiste Daroussinluke.external_dependencies=nil
338*2bc180efSBaptiste Daroussinend
339*2bc180efSBaptiste Daroussinreturn luke
340*2bc180efSBaptiste Daroussinend
341*2bc180efSBaptiste Daroussinreturn{loadluke=function(filename)local content,err=slurp(File(filename))if content==nil then
342*2bc180efSBaptiste Daroussinreturn nil,err
343*2bc180efSBaptiste Daroussinend
344*2bc180efSBaptiste Daroussinlocal r={}local chunk,err=loadstring(content,filename,r)if chunk==nil then
345*2bc180efSBaptiste Daroussinreturn nil,"Error loading file: "..err
346*2bc180efSBaptiste Daroussinend
347*2bc180efSBaptiste Daroussinlocal ok,err=pcall(chunk)if not ok then
348*2bc180efSBaptiste Daroussinreturn nil,"Error running file: "..err
349*2bc180efSBaptiste Daroussinend
350*2bc180efSBaptiste Daroussinr=filter_platforms(r)r.external_dependencies=normalize_configs(r.external_dependencies)r.ldocs=normalize_rules(r.ldocs)r.modules=mapvalues(r.modules,normalize_rules)return r
351*2bc180efSBaptiste Daroussinend,collect_variables=function(luke)return collect_variables(luke,{})end,run_configs=function(L,env,luke)local r=deepcopy(luke)local all_configs=collect_configs(r)sort(all_configs,config_cmp)map(all_configs,function(config)config.t[config.k]=configure(L,env,config.t[config.k],config.module)end)return unwrap_external_dependencies(r)end,run_templates=function(L,env,luke)local r=copy(luke)local rewrite=bind(rewrite_template_files,{L,env})r.modules=mapvalues(r.modules,function(rules)rules.sources=map(rules.sources,rewrite)end)if r.ldocs then
352*2bc180efSBaptiste Daroussinr.ldocs.sources=map(r.ldocs.sources,rewrite)end
353*2bc180efSBaptiste Daroussinreturn r
354*2bc180efSBaptiste Daroussinend,}
355*2bc180efSBaptiste Daroussinend
356*2bc180efSBaptiste Daroussinpackage.preload['luke.platforms']=function()
357*2bc180efSBaptiste Daroussinlocal _ENV=require'std.normalize'{'std.functional',}local CANON={['AIX']=list('aix','unix'),['FreeBSD']=list('freebsd','bsd','unix'),['OpenBSD']=list('openbsd','bsd','unix'),['NetBSD']=list('netbsd','bsd','unix'),['Darwin']=list('macosx','bsd','unix'),['Linux']=list('linux','unix'),['SunOS']=list('solaris','unix'),['^CYGWIN']=list('cygwin','unix'),['^MSYS']=list('msys','cygwin','unix'),['^Windows']=list('win32','windows'),['^MINGW']=list('mingw32','win32','windows'),['^procnto']=list('qnx'),['QNX']=list('qnx'),['Haiku']=list('haiku','unix'),}local ALLPLATFORMS=reduce(values(CANON),function(acc,platforms)map(platforms,function(v)acc[v]=true
358*2bc180efSBaptiste Daroussinend)end)local function match_uname(canon,uname,x)return match(uname,x)and canon[x]end
359*2bc180efSBaptiste Daroussinlocal function toplatforms(canon,uname)local literalkeys,patternkeys=partition(keys(canon),function(k)return sub(k,1,1)~='^'end)return(pluck(literalkeys,canon)or{})[uname]or dropuntil(map(patternkeys,bind(match_uname,{canon,uname})))or list('unix')end
360*2bc180efSBaptiste Daroussinlocal supported=toplatforms(CANON,popen('uname -s'):read'*l')local function isplatform(x)return ALLPLATFORMS[x]~=nil
361*2bc180efSBaptiste Daroussinend
362*2bc180efSBaptiste Daroussinlocal function filter_platforms(t,using,predicate)local r,supported,isplatform={},using or supported,predicate or isplatform
363*2bc180efSBaptiste Daroussinfor k,v in next,t do
364*2bc180efSBaptiste Daroussinif k=='platforms'then
365*2bc180efSBaptiste Daroussinlocal matches=filter(supported,bind(get,{v}))local default=except(keys(v),isplatform)merge(r,hoist(matches,v)or pluck(default,v))elseif istable(v)then
366*2bc180efSBaptiste Daroussinr[k]=filter_platforms(v,supported)else
367*2bc180efSBaptiste Daroussinr[k]=r[k]or v
368*2bc180efSBaptiste Daroussinend
369*2bc180efSBaptiste Daroussinend
370*2bc180efSBaptiste Daroussinreturn r
371*2bc180efSBaptiste Daroussinend
372*2bc180efSBaptiste Daroussinreturn{filter_platforms=filter_platforms,platforms=supported,toplatforms=toplatforms,}
373*2bc180efSBaptiste Daroussinend
374*2bc180efSBaptiste Daroussinpackage.preload['std.functional']=function()
375*2bc180efSBaptiste Daroussinlocal _ENV=require'std.normalize'{destructure=next,isfile=function(x)return io.type(x)=='file'end,wrap=coroutine.wrap,yield=coroutine.yield,}local function apply(fn,argu)assert(fn~=nil,'cannot apply nil-valued function')if iscallable(fn)then
376*2bc180efSBaptiste Daroussinreturn fn(unpack(argu))end
377*2bc180efSBaptiste Daroussinreturn fn
378*2bc180efSBaptiste Daroussinend
379*2bc180efSBaptiste Daroussinlocal function call(fn,...)assert(fn~=nil,'cannot call nil-valued function')if iscallable(fn)then
380*2bc180efSBaptiste Daroussinreturn fn(...)end
381*2bc180efSBaptiste Daroussinreturn fn
382*2bc180efSBaptiste Daroussinend
383*2bc180efSBaptiste Daroussinlocal function wrapnonnil(iterator)return function(...)local r=list(iterator(...))if r[1]~=nil then
384*2bc180efSBaptiste Daroussinreturn r
385*2bc180efSBaptiste Daroussinend
386*2bc180efSBaptiste Daroussinend
387*2bc180efSBaptiste Daroussinend
388*2bc180efSBaptiste Daroussinlocal function each(seq)if type(seq)=='function'then
389*2bc180efSBaptiste Daroussinreturn wrapnonnil(seq)end
390*2bc180efSBaptiste Daroussinlocal i,n=0,int(seq.n)or len(seq)return function()if i<n then
391*2bc180efSBaptiste Daroussini=i+1
392*2bc180efSBaptiste Daroussinreturn list(seq[i])end
393*2bc180efSBaptiste Daroussinend
394*2bc180efSBaptiste Daroussinend
395*2bc180efSBaptiste Daroussinlocal function eq(x)return function(y)return x==y
396*2bc180efSBaptiste Daroussinend
397*2bc180efSBaptiste Daroussinend
398*2bc180efSBaptiste Daroussinlocal function isnonnil(x)return x~=nil
399*2bc180efSBaptiste Daroussinend
400*2bc180efSBaptiste Daroussinlocal function mkpredicate(x)return type(x)=='function'and x or eq(x)end
401*2bc180efSBaptiste Daroussinlocal function except(seq,predicate)predicate=mkpredicate(predicate)local r={}for valu in each(seq)do
402*2bc180efSBaptiste Daroussinif not predicate(unpack(valu))then
403*2bc180efSBaptiste Daroussinr[#r+1]=unpack(valu)end
404*2bc180efSBaptiste Daroussinend
405*2bc180efSBaptiste Daroussinreturn r
406*2bc180efSBaptiste Daroussinend
407*2bc180efSBaptiste Daroussinlocal function visit(x)if type(x)=='table'then
408*2bc180efSBaptiste Daroussinfor valu in each(x)do
409*2bc180efSBaptiste Daroussinvisit(unpack(valu))end
410*2bc180efSBaptiste Daroussinelse
411*2bc180efSBaptiste Daroussinyield(x)end
412*2bc180efSBaptiste Daroussinend
413*2bc180efSBaptiste Daroussinlocal function flatten(...)local r={}for v in wrap(visit),except(list(...),nil)do
414*2bc180efSBaptiste Daroussinr[#r+1]=v
415*2bc180efSBaptiste Daroussinend
416*2bc180efSBaptiste Daroussinreturn r
417*2bc180efSBaptiste Daroussinend
418*2bc180efSBaptiste Daroussinreturn{any=function(seq)for valu in each(seq)do
419*2bc180efSBaptiste Daroussinif unpack(valu)then
420*2bc180efSBaptiste Daroussinreturn true
421*2bc180efSBaptiste Daroussinend
422*2bc180efSBaptiste Daroussinend
423*2bc180efSBaptiste Daroussinreturn false
424*2bc180efSBaptiste Daroussinend,apply=apply,bind=function(fn,bound)local n=bound.n or maxn(bound)return function(...)local argu,unbound=copy(bound),list(...)local i=1
425*2bc180efSBaptiste Daroussinfor j=1,unbound.n do
426*2bc180efSBaptiste Daroussinwhile argu[i]~=nil do
427*2bc180efSBaptiste Daroussini=i+1
428*2bc180efSBaptiste Daroussinend
429*2bc180efSBaptiste Daroussinargu[i],i=unbound[j],i+1
430*2bc180efSBaptiste Daroussinend
431*2bc180efSBaptiste Daroussinbound.n=n>=i and n or i-1
432*2bc180efSBaptiste Daroussinreturn apply(fn,argu)end
433*2bc180efSBaptiste Daroussinend,call=call,case=function(s,branches)if branches[s]~=nil then
434*2bc180efSBaptiste Daroussinreturn call(branches[s],s)end
435*2bc180efSBaptiste Daroussinlocal DEFAULT=1
436*2bc180efSBaptiste Daroussinfor pattern,fn in next,branches do
437*2bc180efSBaptiste Daroussinif pattern~=DEFAULT then
438*2bc180efSBaptiste Daroussinlocal argu=list(match(s,'^'..pattern..'$'))if argu[1]~=nil then
439*2bc180efSBaptiste Daroussinreturn apply(fn,argu)end
440*2bc180efSBaptiste Daroussinend
441*2bc180efSBaptiste Daroussinend
442*2bc180efSBaptiste Daroussinlocal default=branches[DEFAULT]if iscallable(default)then
443*2bc180efSBaptiste Daroussinreturn call(default,s)end
444*2bc180efSBaptiste Daroussinreturn default
445*2bc180efSBaptiste Daroussinend,cond=function(...)for clauseu in each(list(...))do
446*2bc180efSBaptiste Daroussinlocal expr,consequence=destructure(unpack(clauseu))if expr then
447*2bc180efSBaptiste Daroussinreturn call(consequence,expr)end
448*2bc180efSBaptiste Daroussinend
449*2bc180efSBaptiste Daroussinend,contains=function(seq,predicate)if type(predicate)~='function'then
450*2bc180efSBaptiste Daroussinpredicate=eq(predicate)end
451*2bc180efSBaptiste Daroussinfor valu in each(seq)do
452*2bc180efSBaptiste Daroussinif predicate(unpack(valu))then
453*2bc180efSBaptiste Daroussinreturn true
454*2bc180efSBaptiste Daroussinend
455*2bc180efSBaptiste Daroussinend
456*2bc180efSBaptiste Daroussinend,destructure=destructure,dropuntil=function(seq,predicate,block)if block==nil then
457*2bc180efSBaptiste Daroussinpredicate,block=isnonnil,predicate
458*2bc180efSBaptiste Daroussinend
459*2bc180efSBaptiste Daroussinif block~=nil then
460*2bc180efSBaptiste Daroussinfor valu in each(seq)do
461*2bc180efSBaptiste Daroussinlocal r=list(block(unpack(valu)))if predicate(unpack(r))then
462*2bc180efSBaptiste Daroussinreturn unpack(r)end
463*2bc180efSBaptiste Daroussinend
464*2bc180efSBaptiste Daroussinelse
465*2bc180efSBaptiste Daroussinfor r in each(seq)do
466*2bc180efSBaptiste Daroussinif predicate(unpack(r))then
467*2bc180efSBaptiste Daroussinreturn unpack(r)end
468*2bc180efSBaptiste Daroussinend
469*2bc180efSBaptiste Daroussinend
470*2bc180efSBaptiste Daroussinend,except=except,filter=function(seq,predicate)predicate=mkpredicate(predicate)local r={}for valu in each(seq)do
471*2bc180efSBaptiste Daroussinif predicate(unpack(valu))then
472*2bc180efSBaptiste Daroussinr[#r+1]=unpack(valu)end
473*2bc180efSBaptiste Daroussinend
474*2bc180efSBaptiste Daroussinreturn r
475*2bc180efSBaptiste Daroussinend,flatten=flatten,foldkeys=function(keymap,dict,combinator)local r={}for k,v in next,dict or{}do
476*2bc180efSBaptiste Daroussinlocal key=keymap[k]if key then
477*2bc180efSBaptiste Daroussinr[key]=combinator(v,dict[key])else
478*2bc180efSBaptiste Daroussinr[k]=r[k]or v
479*2bc180efSBaptiste Daroussinend
480*2bc180efSBaptiste Daroussinend
481*2bc180efSBaptiste Daroussinreturn r
482*2bc180efSBaptiste Daroussinend,get=function(dict,key)return(dict or{})[key]end,hoist=function(keylist,dict)local r={}for keyu in each(keylist)do
483*2bc180efSBaptiste Daroussinmerge(r,dict[unpack(keyu)])end
484*2bc180efSBaptiste Daroussinreturn next(r)and r or nil
485*2bc180efSBaptiste Daroussinend,id=function(...)return...end,isempty=function(x)return type(x)=='table'and not next(x)end,isfile=isfile,isfunction=function(x)return type(x)=='function'end,isnil=function(x)return x==nil
486*2bc180efSBaptiste Daroussinend,isstring=function(x)return type(x)=='string'end,istable=function(x)return type(x)=='table'end,isnonzero=function(x)return x~=0
487*2bc180efSBaptiste Daroussinend,keys=function(iterable)local r=list()for k in next,iterable or{}do
488*2bc180efSBaptiste Daroussinappend(r,k)end
489*2bc180efSBaptiste Daroussinreturn r
490*2bc180efSBaptiste Daroussinend,map=function(seq,block)local r=list()for valu in each(seq)do
491*2bc180efSBaptiste Daroussinappend(r,block(unpack(valu)))end
492*2bc180efSBaptiste Daroussinreturn r
493*2bc180efSBaptiste Daroussinend,mapvalues=function(iterable,block)local r={}for k,v in next,iterable or{}do
494*2bc180efSBaptiste Daroussinr[k]=block(v)or v
495*2bc180efSBaptiste Daroussinend
496*2bc180efSBaptiste Daroussinreturn r
497*2bc180efSBaptiste Daroussinend,nop=function()end,partition=function(seq,block)local r,s=list(),list()for valu in each(seq)do
498*2bc180efSBaptiste Daroussinappend(block(unpack(valu))and r or s,unpack(valu))end
499*2bc180efSBaptiste Daroussinreturn r,s
500*2bc180efSBaptiste Daroussinend,pluck=function(keylist,dict)local r={}for keyu in each(keylist)do
501*2bc180efSBaptiste Daroussinlocal key=unpack(keyu)r[key]=dict[key]end
502*2bc180efSBaptiste Daroussinreturn next(r)and r or nil
503*2bc180efSBaptiste Daroussinend,reduce=function(seq,acc,block)if block==nil then
504*2bc180efSBaptiste Daroussinacc,block={},acc
505*2bc180efSBaptiste Daroussinend
506*2bc180efSBaptiste Daroussinfor valu in each(seq)do
507*2bc180efSBaptiste Daroussinacc=block(acc,unpack(valu))or acc
508*2bc180efSBaptiste Daroussinend
509*2bc180efSBaptiste Daroussinreturn acc
510*2bc180efSBaptiste Daroussinend,values=function(iterable)local r=list()for _,v in next,iterable or{}do
511*2bc180efSBaptiste Daroussinappend(r,v)end
512*2bc180efSBaptiste Daroussinreturn r
513*2bc180efSBaptiste Daroussinend,zip_with=function(iterable,block)local r=list()for k,v in next,iterable or{}do
514*2bc180efSBaptiste Daroussinappend(r,block(k,v))end
515*2bc180efSBaptiste Daroussinreturn r
516*2bc180efSBaptiste Daroussinend,}
517*2bc180efSBaptiste Daroussinend
518*2bc180efSBaptiste Daroussinpackage.preload['std.normalize']=function()
519*2bc180efSBaptiste Daroussinlocal ceil=math.ceil
520*2bc180efSBaptiste Daroussinlocal concat=table.concat
521*2bc180efSBaptiste Daroussinlocal config=package.config
522*2bc180efSBaptiste Daroussinlocal getmetatable=getmetatable
523*2bc180efSBaptiste Daroussinlocal loadstring=loadstring
524*2bc180efSBaptiste Daroussinlocal match=string.match
525*2bc180efSBaptiste Daroussinlocal next=next
526*2bc180efSBaptiste Daroussinlocal pack=table.pack or function(...)return{n=select('#',...),...}end
527*2bc180efSBaptiste Daroussinlocal setfenv=setfenv
528*2bc180efSBaptiste Daroussinlocal sort=table.sort
529*2bc180efSBaptiste Daroussinlocal tointeger=math.tointeger
530*2bc180efSBaptiste Daroussinlocal tonumber=tonumber
531*2bc180efSBaptiste Daroussinlocal tostring=tostring
532*2bc180efSBaptiste Daroussinlocal type=type
533*2bc180efSBaptiste Daroussinlocal unpack=table.unpack or unpack
534*2bc180efSBaptiste Daroussinlocal dirsep,pathsep,pathmark,execdir,igmark=match(config,'^([^\n]+)\n([^\n]+)\n([^\n]+)\n([^\n]+)\n([^\n]+)')local function copy(iterable)local r={}for k,v in next,iterable or{}do
535*2bc180efSBaptiste Daroussinr[k]=v
536*2bc180efSBaptiste Daroussinend
537*2bc180efSBaptiste Daroussinreturn r
538*2bc180efSBaptiste Daroussinend
539*2bc180efSBaptiste Daroussinlocal int=(function(f)if f==nil then
540*2bc180efSBaptiste Daroussinreturn function(x)if type(x)=='number'and ceil(x)-x==0.0 then
541*2bc180efSBaptiste Daroussinreturn x
542*2bc180efSBaptiste Daroussinend
543*2bc180efSBaptiste Daroussinend
544*2bc180efSBaptiste Daroussinelseif f'1'~=nil then
545*2bc180efSBaptiste Daroussinreturn function(x)if type(x)=='number'then
546*2bc180efSBaptiste Daroussinreturn tointeger(x)end
547*2bc180efSBaptiste Daroussinend
548*2bc180efSBaptiste Daroussinend
549*2bc180efSBaptiste Daroussinreturn f
550*2bc180efSBaptiste Daroussinend)(tointeger)local function iscallable(x)return type(x)=='function'and x or(getmetatable(x)or{}).__call
551*2bc180efSBaptiste Daroussinend
552*2bc180efSBaptiste Daroussinlocal function getmetamethod(x,n)return iscallable((getmetatable(x)or{})[tostring(n)])end
553*2bc180efSBaptiste Daroussinlocal function rawlen(x)if type(x)~='table'then
554*2bc180efSBaptiste Daroussinreturn#x
555*2bc180efSBaptiste Daroussinend
556*2bc180efSBaptiste Daroussinlocal n=#x
557*2bc180efSBaptiste Daroussinfor i=1,n do
558*2bc180efSBaptiste Daroussinif x[i]==nil then
559*2bc180efSBaptiste Daroussinreturn i-1
560*2bc180efSBaptiste Daroussinend
561*2bc180efSBaptiste Daroussinend
562*2bc180efSBaptiste Daroussinreturn n
563*2bc180efSBaptiste Daroussinend
564*2bc180efSBaptiste Daroussinlocal function len(x)local m=getmetamethod(x,'__len')return m and m(x)or rawlen(x)end
565*2bc180efSBaptiste Daroussinif setfenv then
566*2bc180efSBaptiste Daroussinlocal _loadstring=loadstring
567*2bc180efSBaptiste Daroussinloadstring=function(s,filename,env)chunk,err=_loadstring(s,filename)if chunk~=nil and env~=nil then
568*2bc180efSBaptiste Daroussinsetfenv(chunk,env)end
569*2bc180efSBaptiste Daroussinreturn chunk,err
570*2bc180efSBaptiste Daroussinend
571*2bc180efSBaptiste Daroussinelse
572*2bc180efSBaptiste Daroussinloadstring=function(s,filename,env)return load(s,filename,"t",env)end
573*2bc180efSBaptiste Daroussinsetfenv=function()end
574*2bc180efSBaptiste Daroussinend
575*2bc180efSBaptiste Daroussinlocal function keysort(a,b)if int(a)then
576*2bc180efSBaptiste Daroussinreturn int(b)==nil or a<b
577*2bc180efSBaptiste Daroussinelse
578*2bc180efSBaptiste Daroussinreturn int(b)==nil and tostring(a)<tostring(b)end
579*2bc180efSBaptiste Daroussinend
580*2bc180efSBaptiste Daroussinlocal function str(x,roots)roots=roots or{}local function stop_roots(x)return roots[x]or str(x,copy(roots))end
581*2bc180efSBaptiste Daroussinif type(x)~='table'or getmetamethod(x,'__tostring')then
582*2bc180efSBaptiste Daroussinreturn tostring(x)else
583*2bc180efSBaptiste Daroussinlocal buf={'{'}roots[x]=tostring(x)local n,keys=1,{}for k in next,x do
584*2bc180efSBaptiste Daroussinkeys[n],n=k,n+1
585*2bc180efSBaptiste Daroussinend
586*2bc180efSBaptiste Daroussinsort(keys,keysort)local kp
587*2bc180efSBaptiste Daroussinfor _,k in next,keys do
588*2bc180efSBaptiste Daroussinif kp~=nil and k~=nil then
589*2bc180efSBaptiste Daroussinbuf[#buf+1]=type(kp)=='number'and k~=kp+1 and'; 'or', 'end
590*2bc180efSBaptiste Daroussinif k==1 or type(k)=='number'and k-1==kp then
591*2bc180efSBaptiste Daroussinbuf[#buf+1]=stop_roots(x[k])else
592*2bc180efSBaptiste Daroussinbuf[#buf+1]=stop_roots(k)..'='..stop_roots(x[k])end
593*2bc180efSBaptiste Daroussinkp=k
594*2bc180efSBaptiste Daroussinend
595*2bc180efSBaptiste Daroussinbuf[#buf+1]='}'return concat(buf)end
596*2bc180efSBaptiste Daroussinend
597*2bc180efSBaptiste Daroussinreturn setmetatable({append=function(seq,v)local n=(int(seq.n)or len(seq))+1
598*2bc180efSBaptiste Daroussinseq.n,seq[n]=n,v
599*2bc180efSBaptiste Daroussinreturn seq
600*2bc180efSBaptiste Daroussinend,arg=arg,assert=assert,char=string.char,close=io.close,concat=concat,copy=copy,dirsep=dirsep,exit=os.exit,find=string.find,format=string.format,getenv=os.getenv,getmetatable=getmetatable,getmetamethod=getmetamethod,gmatch=string.gmatch,gsub=string.gsub,int=int,iscallable=iscallable,len=len,lines=io.lines,list=pack,loadstring=loadstring,match=string.match,maxn=function(iterable)local n=0
601*2bc180efSBaptiste Daroussinfor k,v in next,iterable or{}do
602*2bc180efSBaptiste Daroussinlocal i=int(k)if i and i>n then
603*2bc180efSBaptiste Daroussinn=i
604*2bc180efSBaptiste Daroussinend
605*2bc180efSBaptiste Daroussinend
606*2bc180efSBaptiste Daroussinreturn n
607*2bc180efSBaptiste Daroussinend,merge=function(r,...)local argu=pack(...)for i=1,argu.n do
608*2bc180efSBaptiste Daroussinfor k,v in next,argu[i]or{}do
609*2bc180efSBaptiste Daroussinr[k]=r[k]or v
610*2bc180efSBaptiste Daroussinend
611*2bc180efSBaptiste Daroussinend
612*2bc180efSBaptiste Daroussinreturn r
613*2bc180efSBaptiste Daroussinend,next=next,open=io.open,pack=pack,pcall=pcall,pop=function(seq)local n,r=seq.n or len(seq)r,seq[n]=seq[n]if int(seq.n)and seq.n>0 then
614*2bc180efSBaptiste Daroussinseq.n=seq.n-1
615*2bc180efSBaptiste Daroussinend
616*2bc180efSBaptiste Daroussinreturn r
617*2bc180efSBaptiste Daroussinend,popen=io.popen,print=print,rawget=rawget,rawset=rawset,rep=string.rep,rm=os.remove,select=select,setmetatable=setmetatable,sort=sort,stderr=io.stderr,stdout=io.stdout,str=str,sub=string.sub,tmpname=os.tmpname,tonumber=tonumber,type=type,unpack=function(seq,i,j)return unpack(seq,int(i)or 1,int(j)or int(seq.n)or len(seq))end,write=io.write,},{__call=function(self,env,level)local userenv,level=copy(self),level or 1
618*2bc180efSBaptiste Daroussinfor name,value in next,env do
619*2bc180efSBaptiste Daroussinif int(name)and type(value)=='string'then
620*2bc180efSBaptiste Daroussinfor k,v in next,(require(value))do
621*2bc180efSBaptiste Daroussinuserenv[k]=userenv[k]or v
622*2bc180efSBaptiste Daroussinend
623*2bc180efSBaptiste Daroussinelse
624*2bc180efSBaptiste Daroussinuserenv[name]=value
625*2bc180efSBaptiste Daroussinend
626*2bc180efSBaptiste Daroussinend
627*2bc180efSBaptiste Daroussinsetfenv(level+1,userenv)return userenv
628*2bc180efSBaptiste Daroussinend,})
629*2bc180efSBaptiste Daroussinend
630*2bc180efSBaptiste Daroussinpackage.preload['type.context-manager']=function()
631*2bc180efSBaptiste Daroussinlocal _ENV=require'std.normalize'{'std.functional',}local contextmanager_mt={__index=function(self,key)if iscallable(self.context[key])then
632*2bc180efSBaptiste Daroussinreturn function(_,...)return self.context[key](self.context,...)end
633*2bc180efSBaptiste Daroussinend
634*2bc180efSBaptiste Daroussinif key=='filename'then
635*2bc180efSBaptiste Daroussinreturn self[1]end
636*2bc180efSBaptiste Daroussinend,}local function ContextManager(release,acquire,...)local fh,err=acquire(...)if not fh then
637*2bc180efSBaptiste Daroussinreturn nil,err
638*2bc180efSBaptiste Daroussinend
639*2bc180efSBaptiste Daroussinlocal cm={context=fh,release=release,n=select("#",...),...}if cm.context~=nil then
640*2bc180efSBaptiste Daroussinsetmetatable(cm,contextmanager_mt)end
641*2bc180efSBaptiste Daroussinreturn cm
642*2bc180efSBaptiste Daroussinend
643*2bc180efSBaptiste Daroussinlocal function context_close(cm)return isfile(cm.context)and close(cm.context)end
644*2bc180efSBaptiste Daroussinlocal function with(...)local argu=list(...)local block=pop(argu)local r=list(apply(block,argu))map(argu,function(cm)if cm~=nil then
645*2bc180efSBaptiste Daroussincm:release()end
646*2bc180efSBaptiste Daroussinend)return unpack(r)end
647*2bc180efSBaptiste Daroussinreturn{ContextManager=ContextManager,CTest=function()local conftest=tmpname()return ContextManager(function(cm)rm(conftest)rm(gsub(conftest,'^.*/','')..'.o')if context_close(cm)then
648*2bc180efSBaptiste Daroussinreturn rm(cm.filename)end
649*2bc180efSBaptiste Daroussinreturn false
650*2bc180efSBaptiste Daroussinend,open,conftest..'.c','w')end,File=function(fname,mode)return ContextManager(context_close,open,fname,mode)end,Pipe=function(cmd,mode)return ContextManager(context_close,popen,cmd,mode)end,TmpFile=function(fname,mode)return ContextManager(function(cm)if context_close(cm)then
651*2bc180efSBaptiste Daroussinreturn rm(cm.filename)end
652*2bc180efSBaptiste Daroussinreturn false
653*2bc180efSBaptiste Daroussinend,open,fname or tmpname(),mode or'w')end,slurp=function(cm,...)if not cm then
654*2bc180efSBaptiste Daroussinreturn cm,...end
655*2bc180efSBaptiste Daroussinreturn with(cm,function(h)return h:read'*a'end)end,with=with,}
656*2bc180efSBaptiste Daroussinend
657*2bc180efSBaptiste Daroussinpackage.preload['type.dict']=function()
658*2bc180efSBaptiste Daroussinlocal _ENV=require'std.normalize'{destructure=next,}return{OrderedDict=function(...)local r,argu={},list(...)for i=1,argu.n do
659*2bc180efSBaptiste Daroussinlocal k,v=destructure(argu[i])append(r,k)r[k]=v
660*2bc180efSBaptiste Daroussinend
661*2bc180efSBaptiste Daroussinreturn r
662*2bc180efSBaptiste Daroussinend,}
663*2bc180efSBaptiste Daroussinend
664*2bc180efSBaptiste Daroussinpackage.preload['type.path']=function()
665*2bc180efSBaptiste Daroussinlocal _ENV=require'std.normalize'{}local BASENAMEPAT='.*'..dirsep
666*2bc180efSBaptiste Daroussinlocal DIRNAMEPAT=dirsep..'[^'..dirsep..']*$'return{basename=function(path)return(gsub(path,BASENAMEPAT,''))end,dirname=function(path)return(gsub(path,DIRNAMEPAT,'',1))end,exists=function(path)local fh=open(path)if fh==nil then
667*2bc180efSBaptiste Daroussinreturn false
668*2bc180efSBaptiste Daroussinend
669*2bc180efSBaptiste Daroussinclose(fh)return true
670*2bc180efSBaptiste Daroussinend,}
671*2bc180efSBaptiste Daroussinend
672*2bc180efSBaptiste Daroussinos.exit(require'luke'.main(arg))
673