ref: 42a043c61a1190130757aa873108ebb2dc8ff386
dir: /deps.myr/
use std use regex use bio use "config.use" use "opts.use" use "types.use" use "util.use" pkg bld = const myrdeps : (p : parser#, dg : depgraph#, targ : byte[:], srcs : byte[:][:], incs : byte[:][:], islib : bool -> bool) /* a bit ugly: initialized from main() */ var usepat : regex.regex# ;; var usepat : regex.regex# type dep = union `Local byte[:] `Lib byte[:] ;; const myrdeps = {p, dg, targ, srcs, incs, islib var seentab, donetab var out, useout var objs, uses var i dg.deps = std.mkht(std.strhash, std.streq) dg.libs = std.mkht(std.strhash, std.streq) dg.sources = std.mkht(std.strhash, std.streq) dg.updated = std.mkht(std.strhash, std.streq) seentab = std.mkht(std.strhash, std.streq) donetab = std.mkht(std.strhash, std.streq) /* direct dependencies of binary */ if islib out = std.fmt("lib%s.a", targ) useout = std.sldup(targ) else out = std.sldup(targ) useout = "" ;; objs = swapall(srcs, config.Objsuffix) uses = swapall(srcs, ".use") for i = 0; i < srcs.len; i++ std.htput(dg.sources, objs[i], srcs[i]) pushdep(dg, srcs[i], objs[i]) if std.hassuffix(srcs[i], ".myr") std.htput(dg.sources, uses[i], srcs[i]) pushdep(dg, srcs[i], uses[i]) ;; ;; for i = 0; i < srcs.len; i++ pushdep(dg, objs[i], out) if islib && std.hassuffix(srcs[i], ".myr") pushdep(dg, uses[i], useout) ;; ;; for i = 0; i < srcs.len; i++ srcdeps(p, dg, seentab, donetab, srcs[i], objs[i], uses[i], incs) ;; dumpgraph(dg) std.htfree(seentab) std.htfree(donetab) -> true } const swapall = {srcs, suff var sl sl = [][:] for s in srcs sl = std.slpush(sl, srcswapsuffix(s, suff)) ;; -> sl } const dumpgraph = {dg var keys if !opt_debug -> ;; keys = std.htkeys(dg.deps) std.put("digraph dg {\n") for k in keys for v in std.htgetv(dg.deps, k, ["WTFUNKNOWN!"][:]) std.put("\t\"%s\" -> \"%s\";\n", k, v) ;; ;; std.put("}\n") } const srcdeps = {p, g, seen, done, path, obj, usefile, incs var deps if std.hthas(done, path) -> elif std.htgetv(seen, path, false) std.fput(1, "dependency loop involving %s\n", path) std.exit(1) ;; deps = getdeps(p, path) std.htput(seen, path, true) for d in deps match d | `Lib lib: scrapelibs(g, lib, incs) | `Local l: if !std.hassuffix(l, ".use") std.fatal(1, "usefile dependency \"%s\" of \"%s\" is not a usefile\n", l, path) ;; if obj.len != 0 pushdep(g, l, obj) ;; if usefile.len != 0 pushdep(g, l, usefile) ;; addusedep(p, g, seen, done, l, incs) ;; ;; std.htput(seen, path, false) std.htput(done, path, true) } const addusedep = {p, g, seen, done, usefile, incs var src if std.hthas(done, usefile) if opt_debug std.put("already loaded deps for %s\n", usefile) ;; -> ;; match std.htget(g.sources, usefile) | `std.Some path: src = std.sldup(path) | `std.None: src = swapsuffix(usefile, ".use", ".myr") ;; pushdep(g, src, usefile) std.htput(g.sources, usefile, src) srcdeps(p, g, seen, done, src, "", usefile, incs) std.htput(done, usefile, true) } const getdeps = {p, path var f var deps : dep[:] deps = [][:] if !std.fexists(path) match std.htget(p.gensrc, path) | `std.Some gt: run(gt.cmd, "") | `std.None: std.fatal(1, "no input file %s\n", path) ;; ;; match bio.open(path, bio.Rd) | `std.Some fd: f = fd | `std.None: std.fatal(1, "could not open %s\n", path) ;; while true match bio.readln(f) | `std.Some ln: deps = depname(deps, ln) std.slfree(ln) | `std.None: bio.close(f) -> deps ;; ;; } const scrapelibs = {dg, lib, incs var deps, d var f var done if std.hthas(dg.libs, lib) -> ;; deps = [][:] f = openlib(lib, incs) match bio.getc(f) | `std.Some 'U': /* nothing */ | `std.Some _: std.fatal(1, "library %s is not usefile\n", lib) | `std.None: std.fatal(1, "library %s is not usefile\n", lib) ;; std.slfree(rdstr(f)) done = false while !done match bio.getc(f) | `std.Some 'L': d = rdstr(f) deps = std.slpush(deps, d) | `std.Some _: done = true | `std.None: done = true ;; ;; bio.close(f) std.htput(dg.libs, lib, deps) for dep in deps scrapelibs(dg, dep, incs) ;; } const openlib = {lib, incs var path for p in incs path = std.pathjoin([p, lib][:]) match bio.open(path, bio.Rd) | `std.Some file: -> file | `std.None: /* nothing */ ;; ;; path = std.pathjoin([opt_instroot, "/lib/myr", lib][:]) match bio.open(path, bio.Rd) | `std.Some file: -> file | `std.None: /* nothing */ ;; std.fatal(1, "could not find library %s.\n", lib) } const depname = {deps, ln /* the regex pattern does some contortions to either grab an unquoted path and put it into uses[4], or a quoted path, and put it (minus the quotes) into uses[2] */ match regex.exec(usepat, ln) | `std.Some uses: if uses[2].len > 0 deps = std.slpush(deps, `Local std.sldup(uses[2])) else deps = std.slpush(deps, `Lib std.sldup(uses[4])) ;; | `std.None: /* nothing to do */ ;; -> deps } /* pushes a dep into the dependency list */ const pushdep = {dg, src, dst var sl if opt_debug std.put("%s <= %s\n", dst, src) ;; std.assert(dst.len < 200, "BUG!") sl = std.htgetv(dg.deps, dst, [][:]) sl = std.slpush(sl, src) std.htput(dg.deps, dst, sl) } const rdstr = {f var len : uint32 var sl match bio.getbe(f) | `std.Some l: len = l sl = std.slalloc(len castto(std.size)) | `std.None: std.die("string length not readable") ;; bio.read(f, sl) -> sl }