Software /
code /
verse
File
buildscripts/squish @ 481:6fc84e9bd03e
squishy: Add browsing plugin
author | Matthew Wild <mwild1@gmail.com> |
---|---|
date | Fri, 17 Mar 2023 12:31:02 +0000 |
parent | 472:864c9dc27c60 |
line wrap: on
line source
#!/usr/bin/lua5.2 package.preload['optlex']=(function(...) local _ENV=_ENV; local function e(t,...) local e=package.loaded[t]or _ENV[t]or{_NAME=t}; package.loaded[t]=e; for t=1,select("#",...)do (select(t,...))(e); end _ENV=e; _M=e; return e; end local s=_G local u=require"string" local i=u.match local e=u.sub local r=u.find local l=u.rep local c error=s.error warn={} local n,o,d local q={ TK_KEYWORD=true, TK_NAME=true, TK_NUMBER=true, TK_STRING=true, TK_LSTRING=true, TK_OP=true, TK_EOS=true, } local b={ TK_COMMENT=true, TK_LCOMMENT=true, TK_EOL=true, TK_SPACE=true, } local h local function k(e) local t=n[e-1] if e<=1 or t=="TK_EOL"then return true elseif t==""then return k(e-1) end return false end local function g(e) local t=n[e+1] if e>=#n or t=="TK_EOL"or t=="TK_EOS"then return true elseif t==""then return g(e+1) end return false end local function E(a) local t=#i(a,"^%-%-%[=*%[") local a=e(a,t+1,-(t-1)) local e,t=1,0 while true do local a,n,i,o=r(a,"([\r\n])([\r\n]?)",e) if not a then break end e=a+1 t=t+1 if#o>0 and i~=o then e=e+1 end end return t end local function v(s,h) local a=i local t,e=n[s],n[h] if t=="TK_STRING"or t=="TK_LSTRING"or e=="TK_STRING"or e=="TK_LSTRING"then return"" elseif t=="TK_OP"or e=="TK_OP"then if(t=="TK_OP"and(e=="TK_KEYWORD"or e=="TK_NAME"))or (e=="TK_OP"and(t=="TK_KEYWORD"or t=="TK_NAME"))then return"" end if t=="TK_OP"and e=="TK_OP"then local t,e=o[s],o[h] if(a(t,"^%.%.?$")and a(e,"^%."))or (a(t,"^[~=<>]$")and e=="=")or (t=="["and(e=="["or e=="="))then return" " end return"" end local t=o[s] if e=="TK_OP"then t=o[h]end if a(t,"^%.%.?%.?$")then return" " end return"" else return" " end end local function j() local a,s,i={},{},{} local e=1 for t=1,#n do local n=n[t] if n~=""then a[e],s[e],i[e]=n,o[t],d[t] e=e+1 end end n,o,d=a,s,i end local function x(r) local t=o[r] local t=t local n if i(t,"^0[xX]")then local e=s.tostring(s.tonumber(t)) if#e<=#t then t=e else return end end if i(t,"^%d+%.?0*$")then t=i(t,"^(%d+)%.?0*$") if t+0>0 then t=i(t,"^0*([1-9]%d*)$") local a=#i(t,"0*$") local o=s.tostring(a) if a>#o+1 then t=e(t,1,#t-a).."e"..o end n=t else n="0" end elseif not i(t,"[eE]")then local a,t=i(t,"^(%d*)%.(%d+)$") if a==""then a=0 end if t+0==0 and a==0 then n="0" else local o=#i(t,"0*$") if o>0 then t=e(t,1,#t-o) end if a+0>0 then n=a.."."..t else n="."..t local a=#i(t,"^0*") local o=#t-a local a=s.tostring(#t) if o+2+#a<1+#t then n=e(t,-o).."e-"..a end end end else local t,a=i(t,"^([^eE]+)[eE]([%+%-]?%d+)$") a=s.tonumber(a) local h,o=i(t,"^(%d*)%.(%d*)$") if h then a=a-#o t=h..o end if t+0==0 then n="0" else local o=#i(t,"^0*") t=e(t,o+1) o=#i(t,"0*$") if o>0 then t=e(t,1,#t-o) a=a+o end local i=s.tostring(a) if a==0 then n=t elseif a>0 and(a<=1+#i)then n=t..l("0",a) elseif a<0 and(a>=-#t)then o=#t+a n=e(t,1,o).."."..e(t,o+1) elseif a<0 and(#i>=-a-#t)then o=-a-#t n="."..l("0",o)..t else n=t.."e"..a end end end if n and n~=o[r]then if h then c("<number> (line "..d[r]..") "..o[r].." -> "..n) h=h+1 end o[r]=n end end local function z(m) local t=o[m] local n=e(t,1,1) local f=(n=="'")and'"'or"'" local t=e(t,2,-2) local a=1 local l,s=0,0 while a<=#t do local c=e(t,a,a) if c=="\\"then local o=a+1 local d=e(t,o,o) local h=r("abfnrtv\\\n\r\"\'0123456789",d,1,true) if not h then t=e(t,1,a-1)..e(t,o) a=a+1 elseif h<=8 then a=a+2 elseif h<=10 then local i=e(t,o,o+1) if i=="\r\n"or i=="\n\r"then t=e(t,1,a).."\n"..e(t,o+2) elseif h==10 then t=e(t,1,a).."\n"..e(t,o+1) end a=a+2 elseif h<=12 then if d==n then l=l+1 a=a+2 else s=s+1 t=e(t,1,a-1)..e(t,o) a=a+1 end else local i=i(t,"^(%d%d?%d?)",o) o=a+1+#i local d=i+0 local h=u.char(d) local r=r("\a\b\f\n\r\t\v",h,1,true) if r then i="\\"..e("abfnrtv",r,r) elseif d<32 then i="\\"..d elseif h==n then i="\\"..h l=l+1 elseif h=="\\"then i="\\\\" else i=h if h==f then s=s+1 end end t=e(t,1,a-1)..i..e(t,o) a=a+#i end else a=a+1 if c==f then s=s+1 end end end if l>s then a=1 while a<=#t do local o,s,i=r(t,"([\'\"])",a) if not o then break end if i==n then t=e(t,1,o-2)..e(t,o) a=o else t=e(t,1,o-1).."\\"..e(t,o) a=o+2 end end n=f end t=n..t..n if t~=o[m]then if h then c("<string> (line "..d[m]..") "..o[m].." -> "..t) h=h+1 end o[m]=t end end local function _(u) local t=o[u] local h=i(t,"^%[=*%[") local a=#h local c=e(t,-a,-1) local s=e(t,a+1,-(a+1)) local n="" local t=1 while true do local a,o,r,h=r(s,"([\r\n])([\r\n]?)",t) local o if not a then o=e(s,t) elseif a>=t then o=e(s,t,a-1) end if o~=""then if i(o,"%s+$")then warn.lstring="trailing whitespace in long string near line "..d[u] end n=n..o end if not a then break end t=a+1 if a then if#h>0 and r~=h then t=t+1 end if not(t==1 and t==a)then n=n.."\n" end end end if a>=3 then local e,t=a-1 while e>=2 do local a="%]"..l("=",e-2).."%]" if not i(n,a)then t=e end e=e-1 end if t then a=l("=",t-2) h,c="["..a.."[","]"..a.."]" end end o[u]=h..n..c end local function w(u) local a=o[u] local h=i(a,"^%-%-%[=*%[") local t=#h local d=e(a,-t,-1) local s=e(a,t+1,-(t-1)) local n="" local a=1 while true do local o,t,r,h=r(s,"([\r\n])([\r\n]?)",a) local t if not o then t=e(s,a) elseif o>=a then t=e(s,a,o-1) end if t~=""then local a=i(t,"%s*$") if#a>0 then t=e(t,1,-(a+1))end n=n..t end if not o then break end a=o+1 if o then if#h>0 and r~=h then a=a+1 end n=n.."\n" end end t=t-2 if t>=3 then local e,a=t-1 while e>=2 do local t="%]"..l("=",e-2).."%]" if not i(n,t)then a=e end e=e-1 end if a then t=l("=",a-2) h,d="--["..t.."[","]"..t.."]" end end o[u]=h..n..d end local function p(a) local t=o[a] local i=i(t,"%s*$") if#i>0 then t=e(t,1,-(i+1)) end o[a]=t end local function A(o,a) if not o then return false end local t=i(a,"^%-%-%[=*%[") local t=#t local i=e(a,-t,-1) local e=e(a,t+1,-(t-1)) if r(e,o,1,true)then return true end end function optimize(t,i,r,a) local m=t["opt-comments"] local u=t["opt-whitespace"] local f=t["opt-emptylines"] local y=t["opt-eols"] local I=t["opt-strings"] local T=t["opt-numbers"] local O=t.KEEP h=t.DETAILS and 0 c=c or s.print if y then m=true u=true f=true end n,o,d =i,r,a local t=1 local a,r local s local function i(i,a,e) e=e or t n[e]=i or"" o[e]=a or"" end while true do a,r=n[t],o[t] local h=k(t) if h then s=nil end if a=="TK_EOS"then break elseif a=="TK_KEYWORD"or a=="TK_NAME"or a=="TK_OP"then s=t elseif a=="TK_NUMBER"then if T then x(t) end s=t elseif a=="TK_STRING"or a=="TK_LSTRING"then if I then if a=="TK_STRING"then z(t) else _(t) end end s=t elseif a=="TK_COMMENT"then if m then if t==1 and e(r,1,1)=="#"then p(t) else i() end elseif u then p(t) end elseif a=="TK_LCOMMENT"then if A(O,r)then if u then w(t) end s=t elseif m then local e=E(r) if b[n[t+1]]then i() a="" else i("TK_SPACE"," ") end if not f and e>0 then i("TK_EOL",l("\n",e)) end if u and a~=""then t=t-1 end else if u then w(t) end s=t end elseif a=="TK_EOL"then if h and f then i() elseif r=="\r\n"or r=="\n\r"then i("TK_EOL","\n") end elseif a=="TK_SPACE"then if u then if h or g(t)then i() else local a=n[s] if a=="TK_LCOMMENT"then i() else local e=n[t+1] if b[e]then if(e=="TK_COMMENT"or e=="TK_LCOMMENT")and a=="TK_OP"and o[s]=="-"then else i() end else local e=v(s,t+1) if e==""then i() else i("TK_SPACE"," ") end end end end end else error("unidentified token encountered") end t=t+1 end j() if y then t=1 if n[1]=="TK_COMMENT"then t=3 end while true do a,r=n[t],o[t] if a=="TK_EOS"then break elseif a=="TK_EOL"then local e,a=n[t-1],n[t+1] if q[e]and q[a]then local e=v(t-1,t+1) if e==""then i() end end end t=t+1 end j() end if h and h>0 then c()end return n,o,d end return{optimize=optimize} end) package.preload['optparser']=(function(...) local _ENV=_ENV; local function e(t,...) local e=package.loaded[t]or _ENV[t]or{_NAME=t}; package.loaded[t]=e; for t=1,select("#",...)do (select(t,...))(e); end _ENV=e; _M=e; return e; end local e=_G local a=require"string" local l=require"table" local s="etaoinshrdlucmfwypvbgkqjxz_ETAOINSHRDLUCMFWYPVBGKQJXZ" local d="etaoinshrdlucmfwypvbgkqjxz_0123456789ETAOINSHRDLUCMFWYPVBGKQJXZ" local w={} for e in a.gmatch([[ and break do else elseif end false for function if in local nil not or repeat return then true until while self _ENV]],"%S+")do w[e]=true end local h,u, m,o, c,v, r, n local function f(e) local i={} for n=1,#e do local e=e[n] local o=e.name if not i[o]then i[o]={ decl=0,token=0,size=0, } end local t=i[o] t.decl=t.decl+1 local i=e.xref local a=#i t.token=t.token+a t.size=t.size+a*#o if e.decl then e.id=n e.xcount=a if a>1 then e.first=i[2] e.last=i[a] end else t.id=n end end return i end local function y(e) local i=a.byte local n=a.char local a={ TK_KEYWORD=true,TK_NAME=true,TK_NUMBER=true, TK_STRING=true,TK_LSTRING=true, } if not e["opt-comments"]then a.TK_COMMENT=true a.TK_LCOMMENT=true end local e={} for t=1,#h do e[t]=u[t] end for t=1,#o do local t=o[t] local a=t.xref for t=1,t.xcount do local t=a[t] e[t]="" end end local t={} for e=0,255 do t[e]=0 end for o=1,#h do local o,e=h[o],e[o] if a[o]then for a=1,#e do local e=i(e,a) t[e]=t[e]+1 end end end local function o(a) local e={} for o=1,#a do local a=i(a,o) e[o]={c=a,freq=t[a],} end l.sort(e, function(t,e) return t.freq>e.freq end ) local t={} for a=1,#e do t[a]=n(e[a].c) end return l.concat(t) end s=o(s) d=o(d) end local function p() local t local n,h=#s,#d local e=r if e<n then e=e+1 t=a.sub(s,e,e) else local i,o=n,1 repeat e=e-i i=i*h o=o+1 until i>e local i=e%n e=(e-i)/n i=i+1 t=a.sub(s,i,i) while o>1 do local i=e%h e=(e-i)/h i=i+1 t=t..a.sub(d,i,i) o=o-1 end end r=r+1 return t,c[t]~=nil end function optimize(e,i,t,s,a) h,u,m,o =i,t,s,a r=0 n={} c=f(m) v=f(o) if e["opt-entropy"]then y(e) end local e={} for t=1,#o do e[t]=o[t] end l.sort(e, function(t,e) return t.xcount>e.xcount end ) local a,t,r={},1,false for o=1,#e do local e=e[o] if not e.preserve then a[t]=e t=t+1 elseif e.name=="self"then r=true end end e=a local s=#e while s>0 do local h,t repeat h,t=p() until not w[h] n[#n+1]=h local a=s if t then local i=m[c[h].id].xref local n=#i for t=1,s do local t=e[t] local s,e=t.act,t.rem while e<0 do e=o[-e].rem end local o for t=1,n do local t=i[t] if t>=s and t<=e then o=true end end if o then t.skip=true a=a-1 end end end while a>0 do local t=1 while e[t].skip do t=t+1 end a=a-1 local i=e[t] t=t+1 i.newname=h i.skip=true i.done=true local s,h=i.first,i.last local r=i.xref if s and a>0 then local n=a while n>0 do while e[t].skip do t=t+1 end n=n-1 local e=e[t] t=t+1 local n,t=e.act,e.rem while t<0 do t=o[-t].rem end if not(h<n or s>t)then if n>=i.act then for o=1,i.xcount do local o=r[o] if o>=n and o<=t then a=a-1 e.skip=true break end end else if e.last and e.last>=i.act then a=a-1 e.skip=true end end end if a==0 then break end end end end local a,t={},1 for o=1,s do local e=e[o] if not e.done then e.skip=false a[t]=e t=t+1 end end e=a s=#e end for e=1,#o do local e=o[e] local t=e.xref if e.newname then for a=1,e.xcount do local t=t[a] u[t]=e.newname end e.name,e.oldname =e.newname,e.name else e.oldname=e.name end end if r then n[#n+1]="self" end local e=f(o) end return{optimize=optimize} end) package.preload['llex']=(function(...) local _ENV=_ENV; local function e(t,...) local e=package.loaded[t]or _ENV[t]or{_NAME=t}; package.loaded[t]=e; for t=1,select("#",...)do (select(t,...))(e); end _ENV=e; _M=e; return e; end local y=_G local s=require"string" local l=s.find local c=s.match local n=s.sub local e='' local r='' local a=1 local d=1 local m={} local w={} local p={} local i='' local v={} for e in s.gmatch([[ and break do else elseif end false for function if in local nil not or repeat return then true until while]],"%S+")do v[e]=true end local function o(a,t) local e=#m+1 m[e]=a w[e]=t p[e]=d end local function h(t,s) local n=n local i=n(e,t,t) t=t+1 local e=n(e,t,t) if(e=="\n"or e=="\r")and(e~=i)then t=t+1 i=i..e end if s then o("TK_EOL",i)end d=d+1 a=t return t end function init(i,t) e=i r=t local t,n,e,i=l(e,"^(#[^\r\n]*)(\r?\n?)") if t then a=a+#e o("TK_COMMENT",e) if#i>0 then h(a,true)end end end function chunkid() if r and c(r,"^[=@]")then return n(r,2) end return"[string]" end function errorline(t,a) local e=error or y.error e(s.format("%s:%d: %s",chunkid(),a or d,t)) end local r=errorline local function u(t) local i=n local n=i(e,t,t) t=t+1 local o=#c(e,"=*",t) t=t+o a=t return(i(e,t,t)==n)and o or(-o)-1 end local function f(d,s) local t=a+1 local n=n local o=n(e,t,t) if o=="\r"or o=="\n"then t=h(t) end local o=t while true do local o,c,l=l(e,"([\r\n%]])",t) if not o then r(d and"unfinished long string"or "unfinished long comment") end t=o if l=="]"then if u(t)==s then i=n(e,i,a) a=a+1 return i end t=a else i=i.."\n" t=h(t) end end end local function b(u) local t=a local s=l local d=n while true do local n,l,o=s(e,"([\n\r\\\"\'])",t) if n then if o=="\n"or o=="\r"then r("unfinished string") end t=n if o=="\\"then t=t+1 o=d(e,t,t) if o==""then break end n=s("abfnrtv\n\r",o,1,true) if n then if n>7 then t=h(t) else t=t+1 end elseif s(o,"%D")then t=t+1 else local o,a,e=s(e,"^(%d%d?%d?)",t) t=a+1 if e+1>256 then r("escape sequence too large") end end else t=t+1 if o==u then a=t return d(e,i,t-1) end end else break end end r("unfinished string") end function llex() local s=l local d=c while true do local t=a while true do local c,m,l=s(e,"^([_%a][_%w]*)",t) if c then a=t+#l if v[l]then o("TK_KEYWORD",l) else o("TK_NAME",l) end break end local l,m,c=s(e,"^(%.?)%d",t) if l then if c=="."then t=t+1 end local u,h,i=s(e,"^%d*[%.%d]*([eE]?)",t) t=h+1 if#i==1 then if d(e,"^[%+%-]",t)then t=t+1 end end local i,t=s(e,"^[_%w]*",t) a=t+1 local e=n(e,l,t) if not y.tonumber(e)then r("malformed number") end o("TK_NUMBER",e) break end local m,w,c,l=s(e,"^((%s)[ \t\v\f]*)",t) if m then if l=="\n"or l=="\r"then h(t,true) else a=w+1 o("TK_SPACE",c) end break end local h=d(e,"^%p",t) if h then i=t local l=s("-[\"\'.=<>~",h,1,true) if l then if l<=2 then if l==1 then local r=d(e,"^%-%-(%[?)",t) if r then t=t+2 local h=-1 if r=="["then h=u(t) end if h>=0 then o("TK_LCOMMENT",f(false,h)) else a=s(e,"[\n\r]",t)or(#e+1) o("TK_COMMENT",n(e,i,a-1)) end break end else local e=u(t) if e>=0 then o("TK_LSTRING",f(true,e)) elseif e==-1 then o("TK_OP","[") else r("invalid long string delimiter") end break end elseif l<=5 then if l<5 then a=t+1 o("TK_STRING",b(h)) break end h=d(e,"^%.%.?%.?",t) else h=d(e,"^%p=?",t) end end a=t+#h o("TK_OP",h) break end local e=n(e,t,t) if e~=""then a=t+1 o("TK_OP",e) break end o("TK_EOS","") return end end end return{ llex=llex, init=init, chunkid=chunkid, tok=m, tokln=p, seminfo=w } end) package.preload['lparser']=(function(...) local _ENV=_ENV; local function e(t,...) local e=package.loaded[t]or _ENV[t]or{_NAME=t}; package.loaded[t]=e; for t=1,select("#",...)do (select(t,...))(e); end _ENV=e; _M=e; return e; end local U=_G local b=require"string" local D={} local T, j, A, C, d, r, P, t,k,l,y, p, a, W, q, N, u, g, E local f,n,w,_,x,v local e=b.gmatch local H={} for e in e("else elseif end until <eof>","%S+")do H[e]=true end local Y={} for e in e("if while do for repeat function local return break","%S+")do Y[e]=e.."_stat" end local S={} local V={} for e,a,t in e([[ {+ 6 6}{- 6 6}{* 7 7}{/ 7 7}{% 7 7} {^ 10 9}{.. 5 4} {~= 3 3}{== 3 3} {< 3 3}{<= 3 3}{> 3 3}{>= 3 3} {and 2 2}{or 1 1} ]],"{(%S+)%s(%d+)%s(%d+)}")do S[e]=a+0 V[e]=t+0 end local Z={["not"]=true,["-"]=true, ["#"]=true,} local ee=8 local function o(t,a) local e=error or U.error e(b.format("(source):%d: %s",a or l,t)) end local function e() P=A[d] t,k,l,y =T[d],j[d],A[d],C[d] d=d+1 end local function X() return T[d] end local function s(a) local e=t if e~="<number>"and e~="<string>"then if e=="<name>"then e=k end e="'"..e.."'" end o(a.." near "..e) end local function c(e) s("'"..e.."' expected") end local function o(a) if t==a then e();return true end end local function L(e) if t~=e then c(e)end end local function i(t) L(t);e() end local function F(e,t) if not e then s(t)end end local function h(e,a,t) if not o(e)then if t==l then c(e) else s("'"..e.."' expected (to close '"..a.."' at line "..t..")") end end end local function c() L("<name>") local t=k p=y e() return t end local function I(e,t) e.k="VK" end local function R(e) I(e,c()) end local function m(o,i) local e=a.bl local t if e then t=e.locallist else t=a.locallist end local e=#u+1 u[e]={ name=o, xref={p}, decl=p, } if i or o=="_ENV"then u[e].preserve=true end local a=#g+1 g[a]=e E[a]=t end local function z(e) local t=#g while e>0 do e=e-1 local t=t-e local a=g[t] local e=u[a] local o=e.name e.act=y g[t]=nil local i=E[t] E[t]=nil local t=i[o] if t then e=u[t] e.rem=-a end i[o]=a end end local function O() local t=a.bl local e if t then e=t.locallist else e=a.locallist end for t,e in U.pairs(e)do local e=u[e] e.rem=y end end local function y(e,t) if b.sub(e,1,1)=="("then return end m(e,t) end local function U(o,a) local t=o.bl local e if t then e=t.locallist while e do if e[a]then return e[a]end t=t.prev e=t and t.locallist end end e=o.locallist return e[a]or-1 end local function b(t,o,e) if t==nil then e.k="VGLOBAL" return"VGLOBAL" else local a=U(t,o) if a>=0 then e.k="VLOCAL" e.id=a return"VLOCAL" else if b(t.prev,o,e)=="VGLOBAL"then return"VGLOBAL" end e.k="VUPVAL" return"VUPVAL" end end end local function Q(o) local t=c() b(a,t,o) if o.k=="VGLOBAL"then local e=N[t] if not e then e=#q+1 q[e]={ name=t, xref={p}, } N[t]=e else local e=q[e].xref e[#e+1]=p end else local e=o.id local e=u[e].xref e[#e+1]=p end end local function p(t) local e={} e.isbreakable=t e.prev=a.bl e.locallist={} a.bl=e end local function b() local e=a.bl O() a.bl=e.prev end local function B() local e if not a then e=W else e={} end e.prev=a e.bl=nil e.locallist={} a=e end local function G() O() a=a.prev end local function U(t) local a={} e() R(a) t.k="VINDEXED" end local function K(t) e() n(t) i("]") end local function M(e) local e,a={},{} if t=="<name>"then R(e) else K(e) end i("=") n(a) end local function O(e) if e.v.k=="VVOID"then return end e.v.k="VVOID" end local function O(e) n(e.v) end local function J(a) local n=l local e={} e.v={} e.t=a a.k="VRELOCABLE" e.v.k="VVOID" i("{") repeat if t=="}"then break end local t=t if t=="<name>"then if X()~="="then O(e) else M(e) end elseif t=="["then M(e) else O(e) end until not o(",")and not o(";") h("}","{",n) end local function X() local i=0 if t~=")"then repeat local t=t if t=="<name>"then m(c()) i=i+1 elseif t=="..."then e() a.is_vararg=true else s("<name> or '...' expected") end until a.is_vararg or not o(",") end z(i) end local function M(n) local a={} local i=l local o=t if o=="("then if i~=P then s("ambiguous syntax (function call x new statement)") end e() if t==")"then a.k="VVOID" else f(a) end h(")","(",i) elseif o=="{"then J(a) elseif o=="<string>"then I(a,k) e() else s("function arguments expected") return end n.k="VCALL" end local function P(a) local t=t if t=="("then local t=l e() n(a) h(")","(",t) elseif t=="<name>"then Q(a) else s("unexpected symbol") end end local function O(a) P(a) while true do local t=t if t=="."then U(a) elseif t=="["then local e={} K(e) elseif t==":"then local t={} e() R(t) M(a) elseif t=="("or t=="<string>"or t=="{"then M(a) else return end end end local function R(o) local t=t if t=="<number>"then o.k="VKNUM" elseif t=="<string>"then I(o,k) elseif t=="nil"then o.k="VNIL" elseif t=="true"then o.k="VTRUE" elseif t=="false"then o.k="VFALSE" elseif t=="..."then F(a.is_vararg==true, "cannot use '...' outside a vararg function"); o.k="VVARARG" elseif t=="{"then J(o) return elseif t=="function"then e() x(o,false,l) return else O(o) return end e() end local function k(o,n) local a=t local i=Z[a] if i then e() k(o,ee) else R(o) end a=t local t=S[a] while t and t>n do local o={} e() local e=k(o,V[a]) a=e t=S[a] end return a end function n(e) k(e,0) end local function I(e) local t={} local e=e.v.k F(e=="VLOCAL"or e=="VUPVAL"or e=="VGLOBAL" or e=="VINDEXED","syntax error") if o(",")then local e={} e.v={} O(e.v) I(e) else i("=") f(t) return end t.k="VNONRELOC" end local function k(e,t) i("do") p(false) z(e) w() b() end local function R(e) local t=r y("(for index)") y("(for limit)") y("(for step)") m(e) i("=") _() i(",") _() if o(",")then _() else end k(1,true) end local function M(e) local t={} y("(for generator)") y("(for state)") y("(for control)") m(e) local e=1 while o(",")do m(c()) e=e+1 end i("in") local a=r f(t) k(e,false) end local function F(e) local a=false Q(e) while t=="."do U(e) end if t==":"then a=true U(e) end return a end function _() local e={} n(e) end local function k() local e={} n(e) end local function S() e() k() i("then") w() end local function P() local t,e={} m(c()) t.k="VLOCAL" z(1) x(e,false,l) end local function U() local e=0 local t={} repeat m(c()) e=e+1 until not o(",") if o("=")then f(t) else t.k="VVOID" end z(e) end function f(e) n(e) while o(",")do n(e) end end function x(a,t,e) B() i("(") if t then y("self",true) z(1) end X() i(")") v() h("end","function",e) G() end function w() p(false) v() b() end function for_stat() local o=r p(true) e() local a=c() local e=t if e=="="then R(a) elseif e==","or e=="in"then M(a) else s("'=' or 'in' expected") end h("end","for",o) b() end function while_stat() local t=r e() k() p(true) i("do") w() h("end","while",t) b() end function repeat_stat() local t=r p(true) p(false) e() v() h("until","repeat",t) k() b() b() end function if_stat() local a=r local o={} S() while t=="elseif"do S() end if t=="else"then e() w() end h("end","if",a) end function return_stat() local a={} e() local e=t if H[e]or e==";"then else f(a) end end function break_stat() local t=a.bl e() while t and not t.isbreakable do t=t.prev end if not t then s("no loop to break") end end function expr_stat() local e={} e.v={} O(e.v) if e.v.k=="VCALL"then else e.prev=nil I(e) end end function function_stat() local a=r local o,t={},{} e() local e=F(o) x(t,e,a) end function do_stat() local t=r e() w() h("end","do",t) end function local_stat() e() if o("function")then P() else U() end end local function i() r=l local e=t local t=Y[e] if t then D[t]() if e=="return"or e=="break"then return true end else expr_stat() end return false end function v() local e=false while not e and not H[t]do e=i() o(";") end end function parser() B() a.is_vararg=true e() v() L("<eof>") G() return q,u end function init(e,o,n) d=1 W={} local t=1 T,j,A,C={},{},{},{} for a=1,#e do local e=e[a] local i=true if e=="TK_KEYWORD"or e=="TK_OP"then e=o[a] elseif e=="TK_NAME"then e="<name>" j[t]=o[a] elseif e=="TK_NUMBER"then e="<number>" j[t]=0 elseif e=="TK_STRING"or e=="TK_LSTRING"then e="<string>" j[t]="" elseif e=="TK_EOS"then e="<eof>" else i=false end if i then T[t]=e A[t]=n[a] C[t]=a t=t+1 end end q,N,u={},{},{} g,E={},{} end D={ expr=n, exp1=_, explist1=f, body=x, block=w, for_stat=for_stat, while_stat=while_stat, repeat_stat=repeat_stat, if_stat=if_stat, return_stat=return_stat, break_stat=break_stat, expr_stat=expr_stat, function_stat=function_stat, do_stat=do_stat, local_stat=local_stat, chunk=v, parser=parser, init=init } return D end) package.preload['minichunkspy']=(function(...) local _ENV=_ENV; local function e(t,...) local e=package.loaded[t]or _ENV[t]or{_NAME=t}; package.loaded[t]=e; for t=1,select("#",...)do (select(t,...))(e); end _ENV=e; _M=e; return e; end local m,t,u=string,table,math local a,v,n,e=ipairs,setmetatable,type,assert local a=__END_OF_GLOBALS__ local c,l,i=m.char,m.byte,m.sub local w,d,g=u.frexp,u.ldexp,u.abs local p=t.concat local a=u.huge local k=a-a local o=false local r=4 local s=4 local h=8 local t={} local function y() t[#t+1] ={o,r,s,h} end local function b() o,r,s,h =unpack(t[#t]) t[#t]=nil end local function t(e,t) return e.new(e,t) end local f={} local t=t{ new= function(e,a) local a=a or{} local t=f[e]or{ __index=e, __call=t } f[e]=t return v(a,t) end, } local j=t{ unpack=function(t,t,e)return nil,e end, pack=function(e,e)return""end } local f={} local function v(e) local t=f[e]or t{ unpack=function(o,a,t) return i(a,t,t+e-1),t+e end, pack=function(a,t)return i(t,1,e)end } f[e]=t return t end local q=t{ unpack=function(a,t,e) return l(t,e,e),e+1 end, pack=function(t,e)return c(e)end } local i=t{ unpack= function(t,e,n) local i,e,t,a=l(e,n,n+3) if o then i,e,t,a=a,t,e,i end return i+e*256+t*256^2+a*256^3,n+4 end, pack= function(t,s) e(n(s)=="number", "unexpected value type to pack as an uint32") local i,a,t,e e=s%2^32 i=e%256;e=(e-i)/256 a=e%256;e=(e-a)/256 t=e%256;e=(e-t)/256 if o then i,a,t,e=e,t,a,i end return c(i,a,t,e) end } local x=t{ unpack= function(a,e,t) local a=i:unpack(e,t) local e=i:unpack(e,t+4) if o then a,e=e,a end return a+e*2^32,t+8 end, pack= function(a,t) e(n(t)=="number", "unexpected value type to pack as an uint64") local e=t%2^32 local t=(t-e)/2^32 if o then e,t=t,e end return i:pack(e)..i:pack(t) end } local function E(e,a) local t=i:unpack(e,a) local e=i:unpack(e,a+4) if o then t,e=e,t end local a=e%2^20 local t=t local o=t+a*2^32 e=(e-a)/2^20 local t=e%2^11 local e=e<=t and 1 or-1 return e,t,o end local function c(n,a,t) local e=t%2^32 local t=(t-e)/2^32 local e=e local t=((n<0 and 2^11 or 0)+a)*2^20+t if o then e,t=t,e end return i.pack(nil,e)..i.pack(nil,t) end local function _(e) if e~=e then return e end if e==0 then e=1/e end return e>0 and 1 or-1 end local l=d(1,-1022-52) local f=l*2^52 local z=d(2^52-1,-1022-52) local f=d(2^53-1,1023-52) e(l~=0 and l/2==0) e(f~=a) e(f*2==a) local d=t{ unpack= function(t,e,i) local n,o,t=E(e,i) local e if o==0 then e=d(t,-1022-52) elseif o==2047 then e=t==0 and a or k else e=d(2^52+t,o-1023-52) end e=n*e return e,i+8 end, pack= function(t,e) if e~=e then return c(1,2047,2^52-1) end local o=_(e) e=g(e) if e==a then return c(o,2047,0)end if e==0 then return c(o,0,0)end local t,a if e<=z then t=0 a=e/l else local o,e=w(e) a=(2*o-1)*2^52 t=e+1022 end return c(o,t,a) end } local a=q local l={ [4]=i, [8]=x } local w={ [4]=float, [8]=d } local c=t{ unpack=function(a,t,e) return l[r]:unpack(t,e) end, pack=function(t,e) return l[r]:pack(e) end, } local i=t{ unpack=function(a,e,t) return l[s]:unpack(e,t) end, pack=function(t,e) return l[s]:pack(e) end, } local g=t{ unpack=function(a,t,e) return w[h]:unpack(t,e) end, pack=function(t,e) return w[h]:pack(e) end, } local k=v(4) local f=t{ unpack= function(t,s,o) local i={} local e,a=1,1 while t[e]do local n=t[e] local t=n.name if not t then t,a=a,a+1 end i[t],o=n:unpack(s,o) e=e+1 end return i,o end, pack= function(a,n) local i={} local e,t=1,1 while a[e]do local o=a[e] local a=o.name if not a then a,t=t,t+1 end i[e]=o:pack(n[a]) e=e+1 end return p(i) end } local d=t{ unpack= function(n,t,e) local o,e=i:unpack(t,e) local a={} local i=n.type for o=1,o do a[o],e=i:unpack(t,e) end return a,e end, pack= function(o,a) local t=#a local e={i:pack(t)} local o=o.type for t=1,t do e[#e+1]=o:pack(a[t]) end return p(e) end } local q=t{ unpack= function(o,a,t) local t,a=i:unpack(a,t) e(t==0 or t==1, "unpacked an unexpected value "..t.." for a Boolean") return t==1,a end, pack= function(a,t) e(n(t)=="boolean", "unexpected value type to pack as a Boolean") return i:pack(t and 1 or 0) end } local c=t{ unpack= function(t,a,e) local t,e=c:unpack(a,e) local o=nil if t>0 then local t=t-1 o=a:sub(e,e+t-1) end return o,e+t end, pack= function(a,t) e(n(t)=="nil"or n(t)=="string", "unexpected value type to pack as a String") if t==nil then return c:pack(0) end return c:pack(#t+1)..t.."\000" end } local p=f{ v(4){name="signature"}, a{name="version"}, a{name="format"}, a{name="endianness"}, a{name="sizeof_int"}, a{name="sizeof_size_t"}, a{name="sizeof_insn"}, a{name="sizeof_Number"}, a{name="integral_flag"}, } local v={ [0]=j, [1]=q, [3]=g, [4]=c, } local g=t{ unpack= function(i,o,t) local t,i=a:unpack(o,t) local a=v[t] e(a,"unknown constant type "..t.." to unpack") local a,o=a:unpack(o,i) if t==3 then e(n(a)=="number") end return{ type=t, value=a },o end, pack= function(t,e) local e,t=e.type,e.value return a:pack(e)..v[e]:pack(t) end } local v=f{ c{name="name"}, i{name="startpc"}, i{name="endpc"} } local a=f{ c{name="name"}, i{name="line"}, i{name="last_line"}, a{name="num_upvalues"}, a{name="num_parameters"}, a{name="is_vararg"}, a{name="max_stack_size"}, d{name="insns",type=k}, d{name="constants",type=g}, d{name="prototypes",type=nil}, d{name="source_lines",type=i}, d{name="locals",type=v}, d{name="upvalues",type=c}, } e(a[10].name=="prototypes", "missed the function prototype list") a[10].type=a local a=t{ unpack= function(i,d,t) local n={} local t,i=p:unpack(d,t) e(t.signature=="\027Lua","signature check failed") e(t.version==81,"version mismatch") e(t.format==0,"format mismatch") e(t.endianness==0 or t.endianness==1,"endianness mismatch") e(l[t.sizeof_int],"int size unsupported") e(l[t.sizeof_size_t],"size_t size unsupported") e(t.sizeof_insn==4,"insn size unsupported") e(w[t.sizeof_Number],"number size unsupported") e(t.integral_flag==0,"integral flag mismatch; only floats supported") y() o=t.endianness==0 r=t.sizeof_size_t s=t.sizeof_int h=t.sizeof_Number n.header=t n.body,i=a:unpack(d,i) b() return n,i end, pack= function(e,t) local i y() local e=t.header o=e.endianness==0 r=e.sizeof_size_t s=e.sizeof_int h=e.sizeof_Number i=p:pack(t.header)..a:pack(t.body) b() return i end } local function o(e) if n(e)=="function"then return o(m.dump(e)) end local t=a:unpack(e,1) local a=a:pack(t) if e==a then return true end local t local t=u.min(#e,#a) for t=1,t do local a=e:sub(t,t) local e=e:sub(t,t) if a~=e then return false,("chunk roundtripping failed: ".. "first byte difference at index %d"):format(t) end end return false,("chunk round tripping failed: ".. "original length %d vs. %d"):format(#e,#a) end return{ disassemble=function(e)return a:unpack(e,1)end, assemble=function(e)return a:pack(e)end, validate=o } end) do local e={}; e["vio"]="local vio = {};\ vio.__index = vio; \ \9\ function vio.open(string)\ \9return setmetatable({ pos = 1, data = string }, vio);\ end\ \ function vio:read(format, ...)\ \9if self.pos >= #self.data then return; end\ \9if format == \"*a\" then\ \9\9local oldpos = self.pos;\ \9\9self.pos = #self.data;\ \9\9return self.data:sub(oldpos, self.pos);\ \9elseif format == \"*l\" then\ \9\9local data;\ \9\9data, self.pos = self.data:match(\"([^\\r\\n]*)\\r?\\n?()\", self.pos)\ \9\9return data;\ \9elseif format == \"*n\" then\ \9\9local data;\ \9\9data, self.pos = self.data:match(\"(%d+)()\", self.pos)\ \9\9return tonumber(data);\9\ \9elseif type(format) == \"number\" then\ \9\9local oldpos = self.pos;\ \9\9self.pos = self.pos + format;\ \9\9return self.data:sub(oldpos, self.pos-1);\ \9end\ end\ \ function vio:seek(whence, offset)\ \9if type(whence) == \"number\" then\ \9\9whence, offset = \"cur\", whence;\ \9end\ \9offset = offset or 0;\ \9\ \9if whence == \"cur\" then\ \9\9self.pos = self.pos + offset;\ \9elseif whence == \"set\" then\ \9\9self.pos = offset + 1;\ \9elseif whence == \"end\" then\ \9\9self.pos = #self.data - offset;\ \9end\ \9\ \9return self.pos;\ end\ \ local function _readline(f) return f:read(\"*l\"); end\ function vio:lines()\ \9return _readline, self;\ end\ \ function vio:write(...)\ \9for i=1,select('#', ...) do\ \9\9local dat = tostring(select(i, ...));\ \9\9self.data = self.data:sub(1, self.pos-1)..dat..self.data:sub(self.pos+#dat, -1);\ \9end\ end\ \ function vio:close()\ \9self.pos, self.data = nil, nil;\ end\ \ "e["gunzip.lua"]="local base_char,keywords=128,{\"and\",\"break\",\"do\",\"else\",\"elseif\",\"end\",\"false\",\"for\",\"function\",\"if\",\"in\",\"local\",\"nil\",\"not\",\"or\",\"repeat\",\"return\",\"then\",\"true\",\"until\",\"while\",\"read\",\"nbits\",\"nbits_left_in_byte\",\"wnd_pos\",\"output\",\"val\",\"input\",}; function prettify(code) return code:gsub(\"[\"..string.char(base_char)..\"-\"..string.char(base_char+#keywords)..\"]\", \ \9function (c) return keywords[c:byte()-base_char]; end) end return setfenv(assert(loadstring(prettify[===[ i,h,b,m,l,d,e,y,r,w,\ u,v,l,l=\ assert,error,ipairs,pairs,tostring,type,setmetatable,io,math,table.sort,\ math.max,string.char,io.open,_G;\ p(n)\ l={};\ e=e({},l)\ l:__index(l)\ n=n(l);e[l]=n\ n\ \ e\ \ l(n,l)\ l=l 1\ h({n},l+1)\ \ _(n)\ l={}\ l.outbs=n\ l.wnd={}\ l.=1\ l\ \ t(l,e)\ n=l.\ l.outbs(e)\ l.wnd[n]=e\ l.=n%32768+1\ \ n(l)\ i(l,'unexpected end of file')\ \ o(n,l)\ n%(l+l)>=l\ \ a=p((l) 2^l )\ c=e({},{__mode='k'})\ g(o)\ l=1\ e={}\ e:()\ n\ l<=#o \ n=o:byte(l)\ l=l+1\ \ n\ \ e\ \ l\ s(d)\ n,l,o=0,0,{};\ o:()\ l\ \ o:(e)\ e=e 1\ l<e \ e=d:()\ e \ n=n+a[l]*e\ l=l+8\ \ o=a[e]\ a=n%o\ n=(n-a)/o\ l=l-e\ a\ \ c[o]=\ o\ \ f(l)\ c[l] l s(g(l))\ \ s(l)\ n\ y.type(l)=='file'\ n=(n)l:write(v(n))\ d(l)=='function'\ n=l\ \ n\ \ d(e,o)\ l={}\ o \ e,n m(e)\ n~=0 \ l[#l+1]={=e,=n}\ \ \ \ n=1,#e-2,2 \ o,n,e=e[n],e[n+1],e[n+2]\ n~=0 \ e=o,e-1 \ l[#l+1]={=e,=n}\ \ \ \ \ w(l,(n,l)\ n.==l. n.<l. n.<l.\ )\ e=1\ o=0\ n,l b(l)\ l.~=o \ e=e*a[l.-o]\ o=l.\ \ l.code=e\ e=e+1\ \ e=r.huge\ c={}\ n,l b(l)\ e=r.min(e,l.)\ c[l.code]=l.\ \ o(n,e)\ l=0\ e=1,e \ e=n%2\ n=(n-e)/2\ l=l*2+e\ \ l\ \ d=p(\ (l) a[e]+o(l,e))\ l:(a)\ o,l=1,0\ 1 \ l==0 \ o=d[n(a:(e))]\ l=l+e\ \ n=n(a:())\ l=l+1\ o=o*2+n\ \ l=c[o]\ l \ l\ \ \ \ l\ \ b(l)\ a=2^1\ e=2^2\ c=2^3\ d=2^4\ n=l:(8)\ n=l:(8)\ n=l:(8)\ n=l:(8)\ t=l:(32)\ t=l:(8)\ t=l:(8)\ o(n,e)\ n=l:(16)\ e=0\ n=1,n \ e=l:(8)\ \ \ o(n,c)\ l:(8)~=0 \ \ o(n,d)\ l:(8)~=0 \ \ o(n,a)\ l:(16)\ \ \ p(l)\ f=l:(5)\ i=l:(5)\ e=n(l:(4))\ a=e+4\ e={}\ o={\ 16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15}\ n=1,a \ l=l:(3)\ n=o[n]\ e[n]=l\ \ e=d(e,)\ r(o)\ t={}\ a\ c=0\ c<o \ o=e:(l)\ e\ o<=15 \ e=1\ a=o\ o==16 \ e=3+n(l:(2))\ o==17 \ e=3+n(l:(3))\ a=0\ o==18 \ e=11+n(l:(7))\ a=0\ \ h'ASSERT'\ \ l=1,e \ t[c]=a\ c=c+1\ \ \ l=d(t,)\ l\ \ n=f+257\ l=i+1\ n=r(n)\ l=r(l)\ n,l\ \ a\ o\ c\ r\ h(e,n,l,d)\ l=l:(e)\ l<256 \ t(n,l)\ l==256 \ \ \ a \ l={[257]=3}\ e=1\ n=258,285,4 \ n=n,n+3 l[n]=l[n-1]+e \ n~=258 e=e*2 \ \ l[285]=258\ a=l\ \ o \ l={}\ e=257,285 \ n=u(e-261,0)\ l[e]=(n-(n%4))/4\ \ l[285]=0\ o=l\ \ a=a[l]\ l=o[l]\ l=e:(l)\ o=a+l\ c \ e={[0]=1}\ l=1\ n=1,29,2 \ n=n,n+1 e[n]=e[n-1]+l \ n~=1 l=l*2 \ \ c=e\ \ r \ n={}\ e=0,29 \ l=u(e-2,0)\ n[e]=(l-(l%2))/2\ \ r=n\ \ l=d:(e)\ a=c[l]\ l=r[l]\ l=e:(l)\ l=a+l\ e=1,o \ l=(n.-1-l)%32768+1\ t(n,i(n.wnd[l],'invalid distance'))\ \ \ \ \ u(l,a)\ i=l:(1)\ e=l:(2)\ r=0\ o=1\ c=2\ f=3\ e==r \ l:(l:())\ e=l:(16)\ o=n(l:(16))\ e=1,e \ l=n(l:(8))\ t(a,l)\ \ e==o e==c \ n,o\ e==c \ n,o=p(l)\ \ n=d{0,8,144,9,256,7,280,8,288,}\ o=d{0,5,32,}\ \ h(\ l,a,n,o\ );\ \ i~=0\ \ e(l)\ n,l=f(l.)\ ,_(s(l.))\ u(n,l)\ \ (n)\ l=f(n.)\ n=s(n.)\ b(l)\ e{=l,=n}\ l:(l:())\ l:()\ \ ]===], '@gunzip.lua')), getfenv())()"e["squish.debug"]="package.preload['minichunkspy']=(function(...)local _ENV=_ENV;local function module(name,...)local t=package.loaded[name]or _ENV[name]or{_NAME=name};package.loaded[name]=t;for i=1,select(\"#\",...)do(select(i,...))(t);end\ _ENV=t;_M=t;return t;end\ local string,table,math=string,table,math\ local ipairs,setmetatable,type,assert=ipairs,setmetatable,type,assert\ local _=__END_OF_GLOBALS__\ local string_char,string_byte,string_sub=string.char,string.byte,string.sub\ local table_concat=table.concat\ local math_abs,math_ldexp,math_frexp=math.abs,math.ldexp,math.frexp\ local Inf=math.huge\ local Nan=Inf-Inf\ local BIG_ENDIAN=false\ local function construct(class,...)return class.new(class,...)end\ local mt_memo={}local Field=construct{new=function(class,self)local self=self or{}local mt=mt_memo[class]or{__index=class,__call=construct}mt_memo[class]=mt\ return setmetatable(self,mt)end,}local None=Field{unpack=function(self,bytes,ix)return nil,ix end,pack=function(self,val)return\"\"end}local char_memo={}local function char(n)local field=char_memo[n]or Field{unpack=function(self,bytes,ix)return string_sub(bytes,ix,ix+n-1),ix+n\ end,pack=function(self,val)return string_sub(val,1,n)end}char_memo[n]=field\ return field\ end\ local uint8=Field{unpack=function(self,bytes,ix)return string_byte(bytes,ix,ix),ix+1\ end,pack=function(self,val)return string_char(val)end}local uint32=Field{unpack=function(self,bytes,ix)local a,b,c,d=string_byte(bytes,ix,ix+3)if BIG_ENDIAN then a,b,c,d=d,c,b,a end\ return a+b*256+c*256^2+d*256^3,ix+4\ end,pack=function(self,val)assert(type(val)==\"number\",\"unexpected value type to pack as an uint32\")local a,b,c,d\ d=val%2^32\ a=d%256;d=(d-a)/256\ b=d%256;d=(d-b)/256\ c=d%256;d=(d-c)/256\ if BIG_ENDIAN then a,b,c,d=d,c,b,a end\ return string_char(a,b,c,d)end}local int32=uint32{unpack=function(self,bytes,ix)local val,ix=uint32:unpack(bytes,ix)return val<2^32 and val or(val-2^31),ix\ end}local Byte=uint8\ local Size_t=uint32\ local Integer=int32\ local Number=char(8)local Insn=char(4)local Struct=Field{unpack=function(self,bytes,ix)local val={}local i,j=1,1\ while self[i]do\ local field=self[i]local key=field.name\ if not key then key,j=j,j+1 end\ val[key],ix=field:unpack(bytes,ix)i=i+1\ end\ return val,ix\ end,pack=function(self,val)local data={}local i,j=1,1\ while self[i]do\ local field=self[i]local key=field.name\ if not key then key,j=j,j+1 end\ data[i]=field:pack(val[key])i=i+1\ end\ return table_concat(data)end}local List=Field{unpack=function(self,bytes,ix)local len,ix=Integer:unpack(bytes,ix)local vals={}local field=self.type\ for i=1,len do\ vals[i],ix=field:unpack(bytes,ix)end\ return vals,ix\ end,pack=function(self,vals)local len=#vals\ local data={Integer:pack(len)}local field=self.type\ for i=1,len do\ data[#data+1]=field:pack(vals[i])end\ return table_concat(data)end}local Boolean=Field{unpack=function(self,bytes,ix)local val,ix=Integer:unpack(bytes,ix)assert(val==0 or val==1,\"unpacked an unexpected value \"..val..\" for a Boolean\")return val==1,ix\ end,pack=function(self,val)assert(type(val)==\"boolean\",\"unexpected value type to pack as a Boolean\")return Integer:pack(val and 1 or 0)end}local String=Field{unpack=function(self,bytes,ix)local len,ix=Integer:unpack(bytes,ix)local val=nil\ if len>0 then\ local string_len=len-1\ val=bytes:sub(ix,ix+string_len-1)end\ return val,ix+len\ end,pack=function(self,val)assert(type(val)==\"nil\"or type(val)==\"string\",\"unexpected value type to pack as a String\")if val==nil then\ return Integer:pack(0)end\ return Integer:pack(#val+1)..val..\"\\0\"end}local ChunkHeader=Struct{char(4){name=\"signature\"},Byte{name=\"version\"},Byte{name=\"format\"},Byte{name=\"endianness\"},Byte{name=\"sizeof_int\"},Byte{name=\"sizeof_size_t\"},Byte{name=\"sizeof_insn\"},Byte{name=\"sizeof_Number\"},Byte{name=\"integral_flag\"},}local ConstantTypes={[0]=None,[1]=Boolean,[3]=Number,[4]=String,}local Constant=Field{unpack=function(self,bytes,ix)local t,ix=Byte:unpack(bytes,ix)local field=ConstantTypes[t]assert(field,\"unknown constant type \"..t..\" to unpack\")local v,ix=field:unpack(bytes,ix)return{type=t,value=v},ix\ end,pack=function(self,val)local t,v=val.type,val.value\ return Byte:pack(t)..ConstantTypes[t]:pack(v)end}local Local=Struct{String{name=\"name\"},Integer{name=\"startpc\"},Integer{name=\"endpc\"}}local Function=Struct{String{name=\"name\"},Integer{name=\"line\"},Integer{name=\"last_line\"},Byte{name=\"num_upvalues\"},Byte{name=\"num_parameters\"},Byte{name=\"is_vararg\"},Byte{name=\"max_stack_size\"},List{name=\"insns\",type=Insn},List{name=\"constants\",type=Constant},List{name=\"prototypes\",type=nil},List{name=\"source_lines\",type=Integer},List{name=\"locals\",type=Local},List{name=\"upvalues\",type=String},}assert(Function[10].name==\"prototypes\",\"missed the function prototype list\")Function[10].type=Function\ local Chunk=Struct{ChunkHeader{name=\"header\"},Function{name=\"body\"}}local function validate(chunk)if type(chunk)==\"function\"then\ return validate(string.dump(chunk))end\ local f=Chunk:unpack(chunk,1)local chunk2=Chunk:pack(f)if chunk==chunk2 then return true end\ local i\ local len=math.min(#chunk,#chunk2)for i=1,len do\ local a=chunk:sub(i,i)local b=chunk:sub(i,i)if a~=b then\ return false,(\"chunk roundtripping failed: \"..\"first byte difference at index %d\"):format(i)end\ end\ return false,(\"chunk round tripping failed: \"..\"original length %d vs. %d\"):format(#chunk,#chunk2)end\ return{disassemble=function(chunk)return Chunk:unpack(chunk,1)end,assemble=function(disassembled)return Chunk:pack(disassembled)end,validate=validate}end)local cs=require\"minichunkspy\"local function ___adjust_chunk(chunk,newname,lineshift)local c=cs.disassemble(string.dump(chunk));c.body.name=newname;lineshift=-c.body.line;local function shiftlines(c)c.line=c.line+lineshift;c.last_line=c.last_line+lineshift;for i,line in ipairs(c.source_lines)do\ c.source_lines[i]=line+lineshift;end\ for i,f in ipairs(c.prototypes)do\ shiftlines(f);end\ end\ shiftlines(c.body);return assert(loadstring(cs.assemble(c),newname))();end\ "function require_resource(t)return e[t]or error("resource '"..tostring(t).."' not found");end end pcall(require,"luarocks.require"); local o={v="verbose",vv="very_verbose",o="output",q="quiet",qq="very_quiet",g="debug"} local e={use_http=false,module_compat=not not _ENV}; for t,a in ipairs(arg)do if a:match("^%-")then local t=a:match("^%-%-?([^%s=]+)()") t=(o[t]or t):gsub("%-+","_"); if t:match("^no_")then t=t:sub(4,-1); e[t]=false; else e[t]=a:match("=(.*)$")or true; end else base_path=a; end end if e.very_verbose then e.verbose=true;end if e.very_quiet then e.quiet=true;end local t=function()end local t,o,s,h=t,t,t,t; if not e.very_quiet then t=print;end if not e.quiet then o=print;end if e.verbose or e.very_verbose then s=print;end if e.very_verbose then h=print;end print=s; local i,d,n={},{},{}; function Module(e) if i[e]then s("Ignoring duplicate module definition for "..e); return function()end end local t=#i+1; i[t]={name=e,url=___fetch_url}; i[e]=i[t]; return function(e) i[t].path=e; end end function Resource(t,a) local e=#n+1; n[e]={name=t,path=a or t}; return function(t) n[e].path=t; end end function AutoFetchURL(e) ___fetch_url=e; end function Main(e) table.insert(d,e); end function Output(t) if e.output==nil then out_fn=t; end end function Option(t) t=t:gsub("%-","_"); if e[t]==nil then e[t]=true; return function(a) e[t]=a; end else return function()end; end end function GetOption(t) return e[t:gsub('%-','_')]; end function Message(t) if not e.quiet then o(t); end end function Error(a) if not e.very_quiet then t(a); end end function Exit() os.exit(1); end base_path=(base_path or"."):gsub("/$","").."/" squishy_file=base_path.."squishy"; out_fn=e.output; local r,a=pcall(dofile,squishy_file); if not r then t("Couldn't read squishy file: "..a); os.exit(1); end if not out_fn then t("No output file specified by user or squishy file"); os.exit(1); elseif#d==0 and#i==0 and#n==0 then t("No files, modules or resources. Not going to generate an empty file."); os.exit(1); end local r={}; function r.filesystem(e) local e,t=io.open(e); if not e then return false,t;end local t=e:read("*a"); e:close(); return t; end if e.use_http then function r.http(t) local e=require"socket.http"; local t,e=e.request(t); if e==200 then return t; end return false,"HTTP status code: "..tostring(e); end else function r.http(e) return false,"Module not found. Re-squish with --use-http option to fetch it from "..e; end end s("Resolving modules..."); do local e=package.config:sub(1,1); local n=package.config:sub(5,5); local o=package.path:gsub("[^;]+",function(t) if not t:match("^%"..e)then return base_path..t; end end):gsub("/%./","/"); local a=package.cpath:gsub("[^;]+",function(t) if not t:match("^%"..e)then return base_path..t; end end):gsub("/%./","/"); function resolve_module(t,a) t=t:gsub("%.",e); for e in a:gmatch("[^;]+")do e=e:gsub("%"..n,t); h("Looking for "..e) local t=io.open(e); if t then h("Found!"); t:close(); return e; end end return nil; end for a,e in ipairs(i)do if not e.path then e.path=resolve_module(e.name,o); if not e.path then t("Couldn't resolve module: "..e.name); else e.path=e.path:gsub("^"..base_path:gsub("%p","%%%1"),""); end end end end for a,e in ipairs(i)do if not e.path then t("Exiting due to missing modules without a path"); os.exit(1); end end if e.list_files or e.list_missing_files then local function t(t) if e.list_missing_files then local e=io.open(t); if e then e:close(); return; end end io.write(t,"\n"); end for a,e in pairs(d)do t(e); end for a,e in ipairs(i)do t(e.path); end for a,e in ipairs(n)do t(e.path); end return; end o("Writing "..out_fn.."..."); local a,l=io.open(out_fn,"w+"); if not a then t("Couldn't open output file: "..tostring(l)); os.exit(1); end if e.executable then if e.executable==true then a:write("#!/usr/bin/env lua\n"); else a:write("#!"..e.executable,"\n"); end end s("Packing modules..."); for o,i in ipairs(i)do local d,s=i.name,i.path; if i.path:sub(1,1)~="/"then s=base_path..i.path; end h("Packing "..d.." ("..s..")..."); local o,n=r.filesystem(s); if(not o)and i.url then local e=i.url:gsub("%?",i.path); h("Fetching: "..e) if e:match("^https?://")then o,n=r.http(e); elseif e:match("^file://")or e:match("^[/%.]")then local e,t=io.open((e:gsub("^file://",""))); if e then o,n=e:read("*a"); e:close(); else o,n=nil,t; end end end if o then o=o:gsub("^#[^\r\n]*\r?\n",""); if not e.debug then a:write("package.preload['",d,"'] = (function (...)\n"); if e.module_compat then a:write[[ local _ENV = _ENV; local function module(name, ...) local t = package.loaded[name] or _ENV[name] or { _NAME = name }; package.loaded[name] = t; for i = 1, select("#", ...) do (select(i, ...))(t); end _ENV = t; _M = t; return t; end ]]; end a:write(o); a:write(" end)\n"); else a:write("package.preload['",d,"'] = assert(loadstring(\n"); a:write(("%q\n"):format(o)); a:write(", ",("%q"):format("@"..s),"))\n"); end else t("Couldn't pack module '"..d.."': "..(n or"unknown error... path to module file correct?")); os.exit(1); end end if#n>0 then s("Packing resources...") a:write("do local resources = {};\n"); for o,e in ipairs(n)do local o,e=e.name,e.path; local e,i=io.open(base_path..e,"rb"); if not e then t("Couldn't load resource: "..tostring(i)); os.exit(1); end local t=e:read("*a"); local e=0; t:gsub("(=+)",function(t)e=math.max(e,#t);end); a:write(("resources[%q] = %q"):format(o,t)); end if e.virtual_io then local e=require_resource("vio"); if not e then t("Virtual IO requested but is not enabled in this build of squish"); else a:write(e,"\n") a:write[[local io_open, io_lines = io.open, io.lines; function io.open(fn, mode) if not resources[fn] then return io_open(fn, mode); else return vio.open(resources[fn]); end end function io.lines(fn) if not resources[fn] then return io_lines(fn); else return vio.open(resources[fn]):lines() end end local _dofile = dofile; function dofile(fn) if not resources[fn] then return _dofile(fn); else return assert(loadstring(resources[fn]))(); end end local _loadfile = loadfile; function loadfile(fn) if not resources[fn] then return _loadfile(fn); else return loadstring(resources[fn], "@"..fn); end end ]] end end a:write[[function require_resource(name) return resources[name] or error("resource '"..tostring(name).."' not found"); end end ]] end h("Finalising...") for e,o in pairs(d)do local e,i=io.open(base_path..o); if not e then t("Failed to open "..o..": "..i); os.exit(1); else a:write((e:read("*a"):gsub("^#.-\n",""))); e:close(); end end a:close(); o("OK!"); local h=require"optlex" local r=require"optparser" local a=require"llex" local d=require"lparser" local i={ none={}; debug={"whitespace","locals","entropy","comments","numbers"}; default={"comments","whitespace","emptylines","numbers","locals"}; basic={"comments","whitespace","emptylines"}; full={"comments","whitespace","emptylines","eols","strings","numbers","locals","entropy"}; } if e.minify_level and not i[e.minify_level]then t("Unknown minify level: "..e.minify_level); t("Available minify levels: none, basic, default, full, debug"); end for a,t in ipairs(i[e.minify_level or"default"]or{})do if e["minify_"..t]==nil then e["minify_"..t]=true; end end local n={ ["opt-locals"]=e.minify_locals; ["opt-comments"]=e.minify_comments; ["opt-entropy"]=e.minify_entropy; ["opt-whitespace"]=e.minify_whitespace; ["opt-emptylines"]=e.minify_emptylines; ["opt-eols"]=e.minify_eols; ["opt-strings"]=e.minify_strings; ["opt-numbers"]=e.minify_numbers; } local function i(e) t("minify: "..e);os.exit(1); end local function l(e) local t=io.open(e,"rb") if not t then i("cannot open \""..e.."\" for reading")end local a=t:read("*a") if not a then i("cannot read from \""..e.."\"")end t:close() return a end local function u(e,a) local t=io.open(e,"wb") if not t then i("cannot open \""..e.."\" for writing")end local a=t:write(a) if not a then i("cannot write to \""..e.."\"")end t:close() end function minify_string(e) a.init(e) a.llex() local t,e,a =a.tok,a.seminfo,a.tokln if n["opt-locals"]then r.print=print d.init(t,e,a) local o,a=d.parser() r.optimize(n,t,e,o,a) end h.print=print t,e,a =h.optimize(n,t,e,a) local e=table.concat(e) if string.find(e,"\r\n",1,1)or string.find(e,"\n\r",1,1)then h.warn.mixedeol=true end return e; end function minify_file(e,t) local e=l(e); e=minify_string(e); u(t,e); end if e.minify~=false then o("Minifying "..out_fn.."..."); minify_file(out_fn,out_fn); o("OK!"); end local h=require"llex" local i=128; local n={"and","break","do","else","elseif", "end","false","for","function","if", "in","local","nil","not","or","repeat", "return","then","true","until","while"} function uglify_file(l,o) local r,a=io.open(l); if not r then t("Can't open input file for reading: "..tostring(a)); return; end local a,s=io.open(o..".uglified","w+b"); if not a then t("Can't open output file for writing: "..tostring(s)); return; end local s=r:read("*a"); r:close(); local r,t=s:match("^(#.-\n)(.+)$"); local t=t or s; if r then a:write(r) end while i+#n<=255 and t:find("["..string.char(i).."-"..string.char(i+#n-1).."]")do i=i+1; end if i+#n>255 then a:write(t); a:close(); os.rename(o..".uglified",o); return; end local d={} for t,e in ipairs(n)do d[e]=string.char(i+t); end local r=0; s:gsub("(=+)",function(e)r=math.max(r,#e);end); h.init(t,"@"..l); h.llex() local s=h.seminfo; if e.uglify_level=="full"and i+#n<255 then local e={}; for o,a in ipairs(h.tok)do if a=="TK_NAME"or a=="TK_STRING"then local t=string.format("%q,%q",a,s[o]); if not e[t]then e[t]={type=a,value=s[o],count=0}; e[#e+1]=e[t]; end e[t].count=e[t].count+1; end end for t=1,#e do local e=e[t]; e.score=(e.count)*(#e.value-1)-#string.format("%q",e.value)-1; end table.sort(e,function(e,t)return e.score>t.score;end); local t=255-(i+#n); for t=t+1,#e do e[t]=nil; end local t=#n; for a,e in ipairs(e)do if e.score>0 then table.insert(n,e.value); d[e.value]=string.char(i+t+a); end end end a:write("local base_char,keywords=",tostring(i),",{"); for t,e in ipairs(n)do a:write(string.format("%q",e),','); end a:write[[}; function prettify(code) return code:gsub("["..string.char(base_char).."-"..string.char(base_char+#keywords).."]", function (c) return keywords[c:byte()-base_char]; end) end ]] a:write[[return setfenv(assert(loadstring(prettify]] a:write("[",string.rep("=",r+1),"["); for e,t in ipairs(h.tok)do if t=="TK_KEYWORD"or t=="TK_NAME"or t=="TK_STRING"then local t=d[s[e]]; if t then a:write(t); else a:write(s[e]); end else a:write(s[e]); end end a:write("]",string.rep("=",r+1),"]"); a:write(", '@",o,"')), getfenv())()"); a:close(); os.rename(o..".uglified",o); end if e.uglify then o("Uglifying "..out_fn.."..."); uglify_file(out_fn,out_fn); o("OK!"); end local i=require"minichunkspy" function compile_string(t,a) local o=string.dump(loadstring(t,a)); if((not e.debug)or e.compile_strip)and e.compile_strip~=false then local t=i.disassemble(o); local function a(e) e.source_lines,e.locals,e.upvalues={},{},{}; for t,e in ipairs(e.prototypes)do a(e); end end s("Stripping debug info..."); a(t.body); return i.assemble(t); end return o; end function compile_file(a,e) local o,a=io.open(a); if not o then t("Can't open input file for reading: "..tostring(a)); return; end local a,i=io.open(e..".compiled","w+"); if not a then t("Can't open output file for writing: "..tostring(i)); return; end local i=o:read("*a"); o:close(); local t,o=i:match("^(#.-\n)(.+)$"); local o=o or i; if t then a:write(t) end a:write(compile_string(o,e)); os.rename(e..".compiled",e); end if e.compile then o("Compiling "..out_fn.."..."); compile_file(out_fn,out_fn); o("OK!"); end function gzip_file(e,a) local o,e=io.open(e); if not o then t("Can't open input file for reading: "..tostring(e)); return; end local e,i=io.open(a..".gzipped","wb+"); if not e then t("Can't open output file for writing: "..tostring(i)); return; end local i=o:read("*a"); o:close(); local n,o=i:match("^(#.-\n)(.+)$"); local o=o or i; if n then e:write(n) end local i,n=io.open(a..".pregzip","wb+"); if not i then t("Can't open temp file for writing: "..tostring(n)); return; end i:write(o); i:close(); local t=io.popen("gzip -c '"..a..".pregzip'"); o=t:read("*a"); t:close(); os.remove(a..".pregzip"); local t=0; o:gsub("(=+)",function(e)t=math.max(t,#e);end); e:write("local ungz = (function ()",require_resource"gunzip.lua"," end)()\n"); e:write[[return assert(loadstring((function (i)local o={} ungz{input=i,output=function(b)table.insert(o,string.char(b))end}return table.concat(o)end) ]]; e:write((string.format("%q",o):gsub("\026","\\026"))); e:write(", '@",a,"'))()"); e:close(); os.rename(a..".gzipped",a); end if e.gzip then o("Gzipping "..out_fn.."..."); gzip_file(out_fn,out_fn); o("OK!"); end