Skip to content

Instantly share code, notes, and snippets.

@duangsuse
Last active August 5, 2024 01:17
Show Gist options
  • Save duangsuse/50937b30cbf24a6be0eb69da3a7231b3 to your computer and use it in GitHub Desktop.
Save duangsuse/50937b30cbf24a6be0eb69da3a7231b3 to your computer and use it in GitHub Desktop.
Developing: tool to cache java main() statics e.g. $ kotlinc
#!/bin/env bash
#kotlinc -include-runtime catdo.kt -d ~/catdo.jar; install -Dm755 -t ~ catdo
catdo() { local k=$1;set -- "$PWD0" "${@:2}"; printf "%s\0" "$@" >buf; printf "%08x" $(wc -c <buf)|basenc --base16 -d >>$k; cat buf>>$k
ruby -e 'k,bf=ARGV; while File.read(bf)!=k do end' $k buf; cat $k
}
[ -z $2 ] &&env JAVACMD=$PWD/catdo $1 &&exit
j=$(echo "$@"|sed -E 's/(\S*Main)/CatdoKt \1/;s/-cp /\0catdo.jar:/')
read f fl <<<$(sed -E 's/.* (\S*Main)(.*)/\1.text \2/'<<<$j)
PWD0="$PWD"
cd
if [ -f "$f" ]; then
echo VM .: jstack $(lsof -t $f)
catdo "$f" $fl;exit
fi
echo $j
nohup java -Djava.security.manager=allow $j 2>&1|tail -n+6 & # :3 "terminally deprecated"?? won't fix System::exit AOP?
import java.io.*
typealias Bytes=ByteArray //..n:i32 i8*n
typealias Pipe<T> =(T)->T
object SystemExit: Error("Re-compute static{}? no way!")
var osExit=0
val out=System.out.also { // ??? https://openjdk.org/jeps/411#:~:text=Blocking%20System::exit%20—%20Some
// 😅Python😅 fixed this(no finally{} when exit()) in design by raise SystemExit
// and even CPython+pip is faster than .main.kts (btw wtf is ".main"?)
System.setSecurityManager(object: SecurityManager() {
override fun checkExit(i:Int){osExit=i;throw SystemExit}
override fun checkPermission(p:java.security.Permission){
if(p.name=="setIO"&&res._v==null)ps.tee()
}
})
}
var ps:PrintStream=out
val jvm=Runtime.getRuntime()
val uBuf=File("buf")
fun PrintStream.tee(){res(1); System.setOut(this);System.setErr(this); res.v<Int>()}
@JvmStatic fun main(vararg cli:String) = bind(File("${cli[0]}.text").apply{deleteOnExit()}) {
//return String(it).reversed().toByteArray()
val argv=it.sep { A,B-> if(B == 0.toByte())1 else -1 }.map { String(it) }
val arg=argv.slice(1..<argv.size).map { listOf("c","").find{c->val u=File(argv[0],it+c); res(if(u.isFile) "$u" else null)}; res.v<String>() ?: it }
var r=""; var mm=0L
//ProcessBuilder(arg).run{start(); waitFor()}
out.print(arg); val ms=measureTime { mm=varDiff{-jvm.freeMemory()}.invoke {
ByteArrayOutputStream().use {
ps=PrintStream(it); ps.tee()
r=try {
unifyErr{ Class.forName(cli[0]).getDeclaredMethod("main", Array<String>::class.java)(null, arg.toTypedArray()) }
"$it" }
catch (e: ClassNotFoundException) {".${cli[0]} NoDef"}
catch (e: NoSuchMethodException) {"${cli[0]} has no main()"}
catch (_: SystemExit) {"$it\n-- $osExit --\n"}
catch (e: Exception) {".${e} e"}
out.print(" ${r.count { it == '\n' } + 1}L ${r.length}c")
}
}}
out.println(" ${ms/1000.0}s ${mm/1024/1024}M")
if(osExit==2)r+="☕️ Simply Ctlr+Shift +Tab for REPLs, or .: rePTYr $(pidof java)\n"
r.toByteArray()
}
fun unifyErr(f:()->Unit)=try{f()}catch(e:Throwable){ var ex=e
while((ex as? java.lang.reflect.InvocationTargetException)!=null) ex=ex.cause!!
throw ex
}
val measureTime=varDiff{System.currentTimeMillis()}
fun varDiff(v: () -> Long)=fun(f:()->Unit)=run {
val v0 = v(); f(); v() - v0
}
fun bind(u:File,f:Pipe<Bytes>) = RandomAccessFile(u, "rw").run {
channel.force(true)
setLength(0);var n=0
while (true) {
while(length().toInt()==n){}
n=readInt(); val ln=Bytes(n); while(read(ln)!=n){}
seek(0); write(f(ln).also{n=it.size})
setLength(n.toLong()); uBuf.writeText(u.name) //just accept(1) + onDiskBuffer
}
} /*
echo=lambda x:x[::-1]
def bind(f, u=open("a.txt",'wb+')):
while True:
while (ln:=u.read())==b'': pass # see also for fd,ev in select.poll():
u.seek(0); u.truncate(0)
u.write(f(ln)); u.flush() #echo >>
bind(echo) */
fun ByteArray.sep(skip: (Byte, Byte) -> Int) = mutableListOf<ByteArray>().also {
var i0 = 0; var d=0
for (i in indices) if(i>0&& skip(this[i - 1], this[i]).also{d=it}!=-1) {
it.add(sliceArray(i0 until i)); i0 = i+d
}
if (i0 < size) {
it.add(sliceArray(i0 until size))
}
}
object res {
var _v=null as Any?
operator fun invoke(v:Any?)=v?.let{_v=it; true} ?: false
fun<T> v()= _v?.let{_v=null;it as T}
}
//4 early bug:
// sep{} don't skip \0 byte, File.exist always false
// mistaken invoke(vararg Str is Str[]); -cp no multiple
// exit()&print*() is not handled
// InvocationTargetException(SystemExit) is error
// #BUG while [ "$k" != "$(cat buf)" ]; do false; done; cat $k
//TODO
// /buf race condition
// sendfile/*
import java.nio.file.*;
import java.util.*;
import java.util.function.*
void main() {
watch(mk(c->{
c.put("a.txt", () -> System.out.println("File modified"));
}));
}
<R> R dd(R x){System.err.println(x);return x;}
<K,V>Map<K,V> mk(Consumer<Map<K,V>> f) { var r=new HashMap<K,V>(); f.accept(r); return r;}
void newPoll(Runnable f) {
new Thread(() -> { while (true) {
f.run();
}}).start();
}
void watch(Map<String, Runnable> c) {try {
var wa = FileSystems.getDefault().newWatchService();
for(var u:c.keySet()) dd(Paths.get( new File(u).getCanonicalFile().getParent())).register(wa, StandardWatchEventKinds.ENTRY_MODIFY);
newPoll(()->{
WatchKey key;
try{key = wa.take();}catch(Exception e){dd(0);return;}
for (WatchEvent<?> event : key.pollEvents()) {
var f=c.get(dd(((Path) event.context()).toString()));
if(f!=null)f.run();
}
key.reset();
});} catch (Exception e) {}
}
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment